Overview

Request 3178 (accepted)

- Update to version 0.17.0:
* rtmp-services: Update ingest list for Restream.io
* Revert "CI: Build on OSX 10.10 on travis"
* Remove python dep
* win-capture: Use static runtimes for hooks/helpers
* cmake: Fix OSX fixup_bundle.sh to copy non-system deps
* cmake: Fix permissions with OSX fixup_bundle.sh
* libobs-opengl: Add xcb message poll to empty out the queue
* frontend-tools: Add options to start output timers every time
* libobs-d3d11: Add optional macro to log shader disassembly
* Revert "obs-transitions: Avoid branching in slide_transition.effect"
* rtmp-services: remove shut down services
* libff: Allow custom demuxer options
* obs-outputs: Fix librtmp IP bind / resolve behavior
* UI: Fix frontend-api event call for adding scenes
* libobs/util: Add function to get circlebuf data offset
* libobs/util: Add function to generate formatted filenames
* libobs: Fix bug where outputs cannot initialize hotkeys
* cmake: Add _CRT_SECURE_NO_WARNINGS to all projects
* libobs: Fix deprecated macro
* libobs/util: Do not ignore deprecation on windows
* libobs: Use reference counting for encoder packets
* obs-ffmpeg: Add replay buffer output
* UI: Disable simple output rec. settings when active
* UI: Add replay buffer options to simple output mode
* UI: Clarify replay buf. hotkey error message
* UI: Separate replay buffer from recording
* UI: Add file prefix/suffix options for replay buffer
* UI: Fix replay buffer compile issues on older compilers
* win-capture: Only duplicate to get cur thread handle
* win-capture: Always use minimal access rights within hook
* win-capture: Do not require pipe/mutex within hook
* win-capture: Fix getting proper UWP window handles
* win-capture: Use window for keepalive check
* win-capture: Create all named objects within hook
* win-capture: Don't use "Local\" for game capture shared mem
* win-capture: Remove redundant function
* win-capture: Use wide strings for named objects
* win-capture: Add ability to open UWP named kernel objects
* win-capture: Open UWP named objects with helper functions
* win-capture: Output hook debug messages if addresses missing
* win-capture: Log plugin-side when capture successful/lost
* win-capture: Don't hook suspended processes
* win-capture: Wait a few frames for hook to load
* win-capture: Fix "attempting to hook [executable]" message
* win-capture: Add ApplicationFrameHost to game capture blacklist
* win-capture: Don't hard fail if thread ID not found
* win-capture: Fix cursor not painting with UWP windows
* win-capture: Add debug messages when hooking
* win-capture: Do not fall back to other windows for UWP windows
* UI: Fix property name bug in frontend API
* libobs: Fix possible reverse order mutex hard lock
* UI: Remove deleteLater view from filter window layout
* libobs: Convert Y800 to RGBX manually
* UI: Use dedicated GPU on Hybrid AMD GPU systems
* libobs: Fix format not being set for new source frames
* libobs: Fix line size issue when copying Y800 data
* obs-ffmpeg: Don't allow 32kb/s with FFmpeg AAC encoder
* libobs/graphics: Fix the 2D vector dot product func
* UI: Make close button default in transform dialog
* UI: Add ability to copy-paste scene item transforms
* UI: Add import/export of scene collections & profiles
* enc-amf: Update to 1.4.3.4 for AMD Driver 16.12.1
* obs-filters: Improve "Color Correction" filter
* image-source: Do not change blend state
* obs-text: Do not reset blend state
* libobs-d3d11: Don't crash if unable to rebuild shared texture
* libobs: Increase maximum audio tracks to 6
* UI: Increase maximum audio tracks to 6
* UI: Update locale for 6 tracks
* UI: Fix endif in installer
* UI: Use 64bit desktop link by default in installer
* UI: Clarify startup error messages related to video
* obs-ffmpeg: Fix nvenc_h264 deprecated message
* libobs: Fix bug drawing RGB/BGR async sources
* libobs: Process all scene audio actions if no audio playing
* UI: Fix buddy controls with new audio tracks
* UI: Add default audio track bitrates
* UI: Fix video initialization failure error message
* UI: Fix settings window stacked widget index
* win-capture: Capture all D3D12 backbuffers
* win-capture: Use FindWindowEx to traverse window list
* win-capture: Fix possible null pointer dereference
* win-capture: Do not add certain windows to window lists
* win-capture: Add a few new blacklisted game capture exes
* obs-filters: Add "Color" option to color correction filter
* obs-filters: Fix comment messages
* obs-qsv11: Use d3d9 allocator on Win7
* win-capture: Fix possible access of array beyond size
* win-capture: Refactor DX12 backbuffer code
* win-capture: If backbuffer count is 1, disable dxgi 1.4 use
* win-capture: Release backbuffers immediately upon init
* libobs/util: Fix C++ compilation issue
* Add libcaption library
* libobs: Add ability to insert captions into frames
* frontend-tools: Move source helper functions to a header
* frontend-tools: Add caption generation tool (windows)
* Update translations from Crowdin
* frontend-tools: Add ability to select caption language
* frontend-tools: Detach caption thread if critical failure
* frontend-tools: Reset stop event before starting captions
* frontend-tools: Don't include colon in "Audio Source"
* frontend-tools: Set buddied controls for captions dialog
* libobs: Fix caption encoder packet reallocation
* libobs: Create referenced parsed AVC encoder packet
* obs-outputs: Free encoder packet data manually
* libobs: Fix bug in AVC encoder packet allocation
* UI: Fix Export QFileDialog parent
* libobs: Eliminate an unnecessary allocation with captions
* frontend-tools: Fix output-timer translation bug
* libobs: Update to version 17.0.0

Submit package home:boombatow...es:Multimedia / obs-studio to package Multimedia / obs-studio

obs-studio.changes Changed
x
 
1
@@ -1,4 +1,119 @@
2
 -------------------------------------------------------------------
3
+Mon Dec 26 08:32:58 UTC 2016 - jimmy@boombatower.com
4
+
5
+- Update to version 0.17.0:
6
+  * rtmp-services: Update ingest list for Restream.io
7
+  * Revert "CI: Build on OSX 10.10 on travis"
8
+  * Remove python dep
9
+  * win-capture: Use static runtimes for hooks/helpers
10
+  * cmake: Fix OSX fixup_bundle.sh to copy non-system deps
11
+  * cmake: Fix permissions with OSX fixup_bundle.sh
12
+  * libobs-opengl: Add xcb message poll to empty out the queue
13
+  * frontend-tools: Add options to start output timers every time
14
+  * libobs-d3d11: Add optional macro to log shader disassembly
15
+  * Revert "obs-transitions: Avoid branching in slide_transition.effect"
16
+  * rtmp-services: remove shut down services
17
+  * libff: Allow custom demuxer options
18
+  * obs-outputs: Fix librtmp IP bind / resolve behavior
19
+  * UI: Fix frontend-api event call for adding scenes
20
+  * libobs/util: Add function to get circlebuf data offset
21
+  * libobs/util: Add function to generate formatted filenames
22
+  * libobs: Fix bug where outputs cannot initialize hotkeys
23
+  * cmake: Add _CRT_SECURE_NO_WARNINGS to all projects
24
+  * libobs: Fix deprecated macro
25
+  * libobs/util: Do not ignore deprecation on windows
26
+  * libobs: Use reference counting for encoder packets
27
+  * obs-ffmpeg: Add replay buffer output
28
+  * UI: Disable simple output rec. settings when active
29
+  * UI: Add replay buffer options to simple output mode
30
+  * UI: Clarify replay buf. hotkey error message
31
+  * UI: Separate replay buffer from recording
32
+  * UI: Add file prefix/suffix options for replay buffer
33
+  * UI: Fix replay buffer compile issues on older compilers
34
+  * win-capture: Only duplicate to get cur thread handle
35
+  * win-capture: Always use minimal access rights within hook
36
+  * win-capture: Do not require pipe/mutex within hook
37
+  * win-capture: Fix getting proper UWP window handles
38
+  * win-capture: Use window for keepalive check
39
+  * win-capture: Create all named objects within hook
40
+  * win-capture: Don't use "Local\" for game capture shared mem
41
+  * win-capture: Remove redundant function
42
+  * win-capture: Use wide strings for named objects
43
+  * win-capture: Add ability to open UWP named kernel objects
44
+  * win-capture: Open UWP named objects with helper functions
45
+  * win-capture: Output hook debug messages if addresses missing
46
+  * win-capture: Log plugin-side when capture successful/lost
47
+  * win-capture: Don't hook suspended processes
48
+  * win-capture: Wait a few frames for hook to load
49
+  * win-capture: Fix "attempting to hook [executable]" message
50
+  * win-capture: Add ApplicationFrameHost to game capture blacklist
51
+  * win-capture: Don't hard fail if thread ID not found
52
+  * win-capture: Fix cursor not painting with UWP windows
53
+  * win-capture: Add debug messages when hooking
54
+  * win-capture: Do not fall back to other windows for UWP windows
55
+  * UI: Fix property name bug in frontend API
56
+  * libobs: Fix possible reverse order mutex hard lock
57
+  * UI: Remove deleteLater view from filter window layout
58
+  * libobs: Convert Y800 to RGBX manually
59
+  * UI: Use dedicated GPU on Hybrid AMD GPU systems
60
+  * libobs: Fix format not being set for new source frames
61
+  * libobs: Fix line size issue when copying Y800 data
62
+  * obs-ffmpeg: Don't allow 32kb/s with FFmpeg AAC encoder
63
+  * libobs/graphics: Fix the 2D vector dot product func
64
+  * UI: Make close button default in transform dialog
65
+  * UI: Add ability to copy-paste scene item transforms
66
+  * UI: Add import/export of scene collections & profiles
67
+  * enc-amf: Update to 1.4.3.4 for AMD Driver 16.12.1
68
+  * obs-filters: Improve "Color Correction" filter
69
+  * image-source: Do not change blend state
70
+  * obs-text: Do not reset blend state
71
+  * libobs-d3d11: Don't crash if unable to rebuild shared texture
72
+  * libobs: Increase maximum audio tracks to 6
73
+  * UI: Increase maximum audio tracks to 6
74
+  * UI: Update locale for 6 tracks
75
+  * UI: Fix endif in installer
76
+  * UI: Use 64bit desktop link by default in installer
77
+  * UI: Clarify startup error messages related to video
78
+  * obs-ffmpeg: Fix nvenc_h264 deprecated message
79
+  * libobs: Fix bug drawing RGB/BGR async sources
80
+  * libobs: Process all scene audio actions if no audio playing
81
+  * UI: Fix buddy controls with new audio tracks
82
+  * UI: Add default audio track bitrates
83
+  * UI: Fix video initialization failure error message
84
+  * UI: Fix settings window stacked widget index
85
+  * win-capture: Capture all D3D12 backbuffers
86
+  * win-capture: Use FindWindowEx to traverse window list
87
+  * win-capture: Fix possible null pointer dereference
88
+  * win-capture: Do not add certain windows to window lists
89
+  * win-capture: Add a few new blacklisted game capture exes
90
+  * obs-filters: Add "Color" option to color correction filter
91
+  * obs-filters: Fix comment messages
92
+  * obs-qsv11: Use d3d9 allocator on Win7
93
+  * win-capture: Fix possible access of array beyond size
94
+  * win-capture: Refactor DX12 backbuffer code
95
+  * win-capture: If backbuffer count is 1, disable dxgi 1.4 use
96
+  * win-capture: Release backbuffers immediately upon init
97
+  * libobs/util: Fix C++ compilation issue
98
+  * Add libcaption library
99
+  * libobs: Add ability to insert captions into frames
100
+  * frontend-tools: Move source helper functions to a header
101
+  * frontend-tools: Add caption generation tool (windows)
102
+  * Update translations from Crowdin
103
+  * frontend-tools: Add ability to select caption language
104
+  * frontend-tools: Detach caption thread if critical failure
105
+  * frontend-tools: Reset stop event before starting captions
106
+  * frontend-tools: Don't include colon in "Audio Source"
107
+  * frontend-tools: Set buddied controls for captions dialog
108
+  * libobs: Fix caption encoder packet reallocation
109
+  * libobs: Create referenced parsed AVC encoder packet
110
+  * obs-outputs: Free encoder packet data manually
111
+  * libobs: Fix bug in AVC encoder packet allocation
112
+  * UI: Fix Export QFileDialog parent
113
+  * libobs: Eliminate an unnecessary allocation with captions
114
+  * frontend-tools: Fix output-timer translation bug
115
+  * libobs: Update to version 17.0.0
116
+
117
+-------------------------------------------------------------------
118
 Mon Nov 21 18:55:11 UTC 2016 - jimmy@boombatower.com
119
 
120
 - Update to version 0.16.6:
121
obs-studio.spec Changed
8
 
1
@@ -1,5 +1,5 @@
2
 Name:           obs-studio
3
-Version:        0.16.6
4
+Version:        0.17.0
5
 Release:        0
6
 Summary:        A recording/broadcasting program
7
 
8
_service Changed
10
 
1
@@ -1,7 +1,7 @@
2
 <services>
3
   <service name="tar_scm" mode="disabled">
4
     <param name="versionformat">@PARENT_TAG@</param>
5
-    <param name="revision">refs/tags/0.16.6</param>
6
+    <param name="revision">refs/tags/0.17.0</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
@@ -1,6 +1,6 @@
2
 <servicedata>
3
   <service name="tar_scm">
4
     <param name="url">git://github.com/jp9000/obs-studio.git</param>
5
-    <param name="changesrevision">b7b8ad476f1f62376833a224d64aa7b747d3b58b</param>
6
+    <param name="changesrevision">93e084088f3c1f3979d78eea3c5d9220b1cea3f7</param>
7
   </service>
8
 </servicedata>
9
obs-studio-0.16.6.tar.xz/plugins/enc-amf/CONTRIBUTORS.md Deleted
88
 
1
@@ -1,85 +0,0 @@
2
-# The Great Contributors
3
-
4
-These great People have helped create this plugin:
5
-
6
-| Who | What |
7
-| --- | ---- |
8
-| [jackun](http://github.com/jackun) | The awesome person that started it all with his own Classic and Studio fork.<br>Thanks to him this project even exists today. |
9
-| [Xaymar](http://github.com/Xaymar) | Just the guy who spent a week staring at his monitors, trying to figure out how to make it work. |
10
-| [leporel](https://github.com/leporel) | Provided ru-RU language files (Russian) |
11
-| [max20091](https://github.com/max20091) | Provided vi-VN language files (Vietnamese) |
12
-| [M4RK22](https://github.com/M4RK22) | Provided es-ES language files (Spanish) |
13
-| [niteforce](https://github.com/niteforce) | Provided hu-HU language files (Hungarian) |
14
-| [nwgat](https://github.com/nwgat) | Provided nb-NO language files (Norwegian) |
15
-| [wazerstar](https://github.com/wazerstar) | Provided da-DK language files (Danish) |
16
-| [Jim](https://github.com/jp9000) | General OBS Support for development questions. |
17
-| GolDAce | CrowdIn integration stuff. |
18
-
19
-# The Amazing Supporters
20
-
21
-And these great people have decided to support the project by one or another means.
22
-
23
-## September 2016
24
-### Marcos Vidal
25
-Spanish translator.  
26
-[Website](https://markitos.ovh), [Steam](http://steamcommunity.com/id/markitos22/)
27
-
28
-### nwgat.ninja
29
-nwgat.ninja is proud to support Xaymars Technology Projects.  
30
-[Website](https://nwgat.ninja)
31
-
32
-### AJ
33
-Este espacio para el alquiler.
34
-
35
-### Jeremy "razorlikes" Nieth
36
-I like to support this project becuase it gives me a way to stream without having to sacrifice immense amounts of cpu resources for encoding.  
37
-[Twitch](https://twitch.tv/razorlikes), [GitHub](https://github.com/razorlikes)
38
-
39
-### Kristian Kirkes(ae)ther
40
-Kristian has not been able to provide a comment in time.
41
-
42
-### Markus Wiegand
43
-Earth has not been able to find Markus and make him respond in time.
44
-[Twitter](https://twitter.com/Morphy2k/), [GitHub](https://github.com/Morphy2k)
45
-
46
-### SneakyJoe
47
-Russian streamer and stream teacher, AMD fanboy. Wants to make AMD great again.  
48
-[Website](http://sneakyjoe.ru/), [YouTube](https://www.youtube.com/channel/UCUmRv5GwQcsnxXRzuPCGr-Q)
49
-
50
-### vektorDex
51
-Well, he's my big brother. Could at least have responded. ;_; (just kidding)
52
-[Website](http://blog-of-dex.de/), [Twitter](https://twitter.com/vektordex), [Studio](http://digitaldawnstudios.com)
53
-
54
-### Daniel Bagge
55
-Kini nga luna alang sa abang.
56
-
57
-### John Difool
58
-John Difool der alte Sack
59
-[YouTube](https://www.youtube.com/channel/UC5FPsFLQh4ah0-vz-eoZlOA)
60
-
61
-### Nucu
62
-Thanks AMD and Xaymar to make hardware encoding possible.
63
-
64
-### DaOrgest
65
-Currently studying computer and I do YouTube for a hobby
66
-
67
-[Website](http://daorgest.me), [YouTube](http://youtube.com/daorgest)
68
-
69
-## August 2016
70
-### Jeremy Nieth
71
-Jeremy has decided to not specify what he wanted to be written here. So this will have to do for now.
72
-
73
-### Marcos Vidal
74
-Spanish translator.  
75
-[Website](https://markitos.ovh), [Steam](http://steamcommunity.com/id/markitos22/)
76
-
77
-### Markus Wiegand
78
-Markus has also decided to not specify what should be here. So instead, I've decided to write these two sentences for him.  
79
-[Twitter](https://twitter.com/Morphy2k/), [GitHub](https://github.com/Morphy2k)
80
-
81
-### nwgat.ninja
82
-nwgat.ninja is proud to support Xaymars Technology Projects.  
83
-[Website](https://nwgat.ninja)
84
-
85
-### Nico Thate
86
-Even though he has chosen to not receive a reward for being a patron, he'll get an entry anyway.
87
\ No newline at end of file
88
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Include/amd-amf-vce-capabilities.h Deleted
108
 
1
@@ -1,105 +0,0 @@
2
-/*
3
-MIT License
4
-
5
-Copyright (c) 2016 Michael Fabian Dirks
6
-
7
-Permission is hereby granted, free of charge, to any person obtaining a copy
8
-of this software and associated documentation files (the "Software"), to deal
9
-in the Software without restriction, including without limitation the rights
10
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
-copies of the Software, and to permit persons to whom the Software is
12
-furnished to do so, subject to the following conditions:
13
-
14
-The above copyright notice and this permission notice shall be included in all
15
-copies or substantial portions of the Software.
16
-
17
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
-SOFTWARE.
24
-*/
25
-
26
-#pragma once
27
-//////////////////////////////////////////////////////////////////////////
28
-// Includes
29
-//////////////////////////////////////////////////////////////////////////
30
-#include <stdint.h>
31
-#include <inttypes.h>
32
-#include <vector>
33
-#include <list>
34
-#include <map>
35
-
36
-// Plugin
37
-#include "plugin.h"
38
-#include "amd-amf.h"
39
-#include "amd-amf-vce.h"
40
-#include "api-base.h"
41
-
42
-// AMF
43
-#include "components\ComponentCaps.h"
44
-
45
-//////////////////////////////////////////////////////////////////////////
46
-// Code
47
-//////////////////////////////////////////////////////////////////////////
48
-
49
-namespace Plugin {
50
-   namespace AMD {
51
-       struct VCEDeviceCapabilities {
52
-           amf::AMF_ACCELERATION_TYPE acceleration_type;
53
-           uint32_t maxProfile;
54
-           uint32_t maxProfileLevel;
55
-           uint32_t maxBitrate;
56
-           uint32_t minReferenceFrames;
57
-           uint32_t maxReferenceFrames;
58
-           bool supportsBFrames;
59
-           bool supportsFixedSliceMode;
60
-           uint32_t maxTemporalLayers;
61
-           uint32_t maxNumOfStreams;
62
-           uint32_t maxNumOfHwInstances;
63
-
64
-           struct IOCaps {
65
-               int32_t minWidth, maxWidth;
66
-               int32_t minHeight, maxHeight;
67
-               bool isInterlacedSupported;
68
-               uint32_t verticalAlignment;
69
-
70
-               std::vector<std::pair<amf::AMF_SURFACE_FORMAT, bool>> formats;
71
-               std::vector<std::pair<amf::AMF_MEMORY_TYPE, bool>> memoryTypes;
72
-           } input, output;
73
-       };
74
-
75
-       class VCECapabilities {
76
-           //////////////////////////////////////////////////////////////////////////
77
-           // Singleton
78
-           //////////////////////////////////////////////////////////////////////////
79
-           public:
80
-           static std::shared_ptr<Plugin::AMD::VCECapabilities> GetInstance();
81
-           static void ReportCapabilities();
82
-           static void ReportDeviceCapabilities(Plugin::API::Device device);
83
-           static void ReportDeviceIOCapabilities(Plugin::API::Device device, VCEEncoderType type, bool output);
84
-
85
-           //////////////////////////////////////////////////////////////////////////
86
-           // Class
87
-           //////////////////////////////////////////////////////////////////////////
88
-           public:
89
-           VCECapabilities();
90
-           ~VCECapabilities();
91
-
92
-           //void QueryCapabilitiesForDevice(VCEMemoryType type, Plugin::API::Device device = Plugin::API::Device());
93
-
94
-           bool Refresh();
95
-           std::vector<Plugin::API::Device> GetDevices();
96
-           VCEDeviceCapabilities GetDeviceCaps(Plugin::API::Device device, VCEEncoderType type);
97
-           VCEDeviceCapabilities::IOCaps GetDeviceIOCaps(Plugin::API::Device device, VCEEncoderType type, bool output);
98
-
99
-           private:
100
-           //std::map<VCEMemoryType, std::map<Plugin::API::Device, std::map<VCEEncoderType, VCEDeviceCapabilities>>> tstMap;
101
-
102
-           std::vector<Plugin::API::Device> devices;
103
-           std::map<std::pair<Plugin::API::Device, Plugin::AMD::VCEEncoderType>, VCEDeviceCapabilities> deviceToCapabilities;
104
-       };
105
-   }
106
-}
107
\ No newline at end of file
108
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Include/amd-amf-vce.h Deleted
503
 
1
@@ -1,500 +0,0 @@
2
-/*
3
-MIT License
4
-
5
-Copyright (c) 2016 Michael Fabian Dirks
6
-
7
-Permission is hereby granted, free of charge, to any person obtaining a copy
8
-of this software and associated documentation files (the "Software"), to deal
9
-in the Software without restriction, including without limitation the rights
10
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
-copies of the Software, and to permit persons to whom the Software is
12
-furnished to do so, subject to the following conditions:
13
-
14
-The above copyright notice and this permission notice shall be included in all
15
-copies or substantial portions of the Software.
16
-
17
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
-SOFTWARE.
24
-*/
25
-
26
-#pragma once
27
-//////////////////////////////////////////////////////////////////////////
28
-// Includes
29
-//////////////////////////////////////////////////////////////////////////
30
-#include <condition_variable>
31
-#include <algorithm>
32
-#include <mutex>
33
-#include <queue>
34
-#include <thread>
35
-#include <vector>
36
-#include <chrono>
37
-
38
-// Plugin
39
-#include "plugin.h"
40
-#include "amd-amf.h"
41
-#include "api-base.h"
42
-
43
-//////////////////////////////////////////////////////////////////////////
44
-// Code
45
-//////////////////////////////////////////////////////////////////////////
46
-
47
-namespace Plugin {
48
-   namespace AMD {
49
-       // Internal Properties
50
-       enum VCEEncoderType {
51
-           VCEEncoderType_AVC,     // Advanced Video Coding
52
-           VCEEncoderType_SVC,     // Scalable Video Coding
53
-           VCEEncoderType_HEVC,    // High-Efficiency Video Coding (Discovered in amfrt64.dll)
54
-       };
55
-       enum VCEMemoryType {
56
-           VCEMemoryType_Host,         // Host-Managed Memory
57
-           VCEMemoryType_DirectX9,     // DirectX9
58
-           VCEMemoryType_DirectX11,    // DirectX11
59
-           VCEMemoryType_OpenGL,       // OpenGL
60
-       };
61
-       enum VCEColorFormat {
62
-           // 4:2:0 Formats
63
-           VCEColorFormat_NV12,    // NV12
64
-           VCEColorFormat_I420,    // YUV 4:2:0
65
-           // 4:2:2 Formats
66
-           VCEColorFormat_YUY2,
67
-           // Uncompressed
68
-           VCEColorFormat_BGRA,    // ARGB
69
-           VCEColorFormat_RGBA,    // RGBA
70
-           // Other
71
-           VCEColorFormat_GRAY,
72
-       };
73
-       enum VCEColorProfile {
74
-           VCEColorProfile_601,
75
-           VCEColorProfile_709,
76
-           VCEColorProfile_2020, // HDR
77
-       };
78
-
79
-       // Static Properties
80
-       enum VCEUsage {
81
-           VCEUsage_Transcoding,
82
-           VCEUsage_UltraLowLatency,
83
-           VCEUsage_LowLatency,
84
-           VCEUsage_Webcam,            // For SVC
85
-       };
86
-       enum VCEQualityPreset {
87
-           VCEQualityPreset_Speed,
88
-           VCEQualityPreset_Balanced,
89
-           VCEQualityPreset_Quality,
90
-       };
91
-       enum VCEProfile {
92
-           VCEProfile_Baseline = 66,
93
-           VCEProfile_Main = 77,
94
-           VCEProfile_High = 100,
95
-           VCEProfile_ConstrainedBaseline = 256,
96
-           VCEProfile_ConstrainedHigh = 257
97
-       };
98
-       enum VCEProfileLevel {
99
-           VCEProfileLevel_Automatic = 0,
100
-           VCEProfileLevel_10 = 10,
101
-           VCEProfileLevel_11,
102
-           VCEProfileLevel_12,
103
-           VCEProfileLevel_13,
104
-           VCEProfileLevel_20 = 20,
105
-           VCEProfileLevel_21,
106
-           VCEProfileLevel_22,
107
-           VCEProfileLevel_30 = 30,
108
-           VCEProfileLevel_31,
109
-           VCEProfileLevel_32,
110
-           VCEProfileLevel_40 = 40,
111
-           VCEProfileLevel_41,
112
-           VCEProfileLevel_42,
113
-           VCEProfileLevel_50 = 50,
114
-           VCEProfileLevel_51,
115
-           VCEProfileLevel_52,
116
-           VCEProfileLevel_60 = 60,
117
-           VCEProfileLevel_61,
118
-           VCEProfileLevel_62,
119
-       };
120
-       enum VCEScanType {
121
-           VCEScanType_Progressive,
122
-           VCEScanType_Interlaced,
123
-       };
124
-       enum VCECodingType {
125
-           VCECodingType_Default,
126
-           VCECodingType_CALV,
127
-           VCECodingType_CABAC,
128
-       };
129
-
130
-       // Dynamic Properties
131
-       enum VCERateControlMethod {
132
-           VCERateControlMethod_ConstantQP,
133
-           VCERateControlMethod_ConstantBitrate,
134
-           VCERateControlMethod_VariableBitrate_PeakConstrained,
135
-           VCERateControlMethod_VariableBitrate_LatencyConstrained,
136
-       };
137
-       enum VCEBPicturePattern {
138
-           VCEBPicturePattern_None,
139
-           VCEBPicturePattern_One,
140
-           VCEBPicturePattern_Two,
141
-           VCEBPicturePattern_Three,
142
-       };
143
-
144
-       class VCEEncoder {
145
-           //////////////////////////////////////////////////////////////////////////
146
-           #pragma region Functions
147
-           //////////////////////////////////////////////////////////////////////////
148
-           private:
149
-           static void InputThreadMain(Plugin::AMD::VCEEncoder* p_this);
150
-           static void OutputThreadMain(Plugin::AMD::VCEEncoder* p_this);
151
-
152
-           #pragma endregion Functions
153
-           //////////////////////////////////////////////////////////////////////////
154
-
155
-           //////////////////////////////////////////////////////////////////////////
156
-           #pragma region Initializer & Finalizer
157
-           //////////////////////////////////////////////////////////////////////////
158
-           public:
159
-           VCEEncoder(VCEEncoderType p_Type,
160
-               std::string p_DeviceId = "",
161
-               bool p_OpenCL = false,
162
-               VCEColorFormat p_SurfaceFormat = VCEColorFormat_NV12
163
-           );
164
-           ~VCEEncoder();
165
-           #pragma endregion Initializer & Finalizer
166
-
167
-           //////////////////////////////////////////////////////////////////////////
168
-           #pragma region Methods
169
-           //////////////////////////////////////////////////////////////////////////
170
-           public:
171
-           void Start();
172
-           void Restart();
173
-           void Stop();
174
-           bool IsStarted();
175
-           bool SendInput(struct encoder_frame* frame);
176
-           bool GetOutput(struct encoder_packet* packet, bool* received_packet);
177
-           bool GetExtraData(uint8_t**& data, size_t*& size);
178
-           void GetVideoInfo(struct video_scale_info*& vsi);
179
-
180
-           // Threading
181
-           private:
182
-           void InputThreadLogic();
183
-           void OutputThreadLogic();
184
-
185
-           // Utility
186
-           inline amf::AMFSurfacePtr CreateSurfaceFromFrame(struct encoder_frame*& frame);
187
-
188
-           public:
189
-           void LogProperties();
190
-           
191
-           /************************************************************************/
192
-           /* Static Properties                                                    */
193
-           /************************************************************************/
194
-
195
-           /*  Usage Type
196
-           *   Sets up the entire encoder to a specific set of properties.
197
-           *   Must be called first if you want to override properties. */
198
-           void SetUsage(VCEUsage usage);
199
-           VCEUsage GetUsage();
200
-
201
-           /** Quality Preset
202
-           * Static Property, changes cause a restart. */
203
-           void SetQualityPreset(VCEQualityPreset preset);
204
-           VCEQualityPreset GetQualityPreset();
205
-           
206
-           /*  H.264 Profile */
207
-           void SetProfile(VCEProfile profile);
208
-           VCEProfile GetProfile();
209
-
210
-           /*  H.264 Profile Level */
211
-           void SetProfileLevel(VCEProfileLevel level);
212
-           VCEProfileLevel GetProfileLevel();
213
-
214
-           /*  The number of long-term references controlled by the user.
215
-            *
216
-            *  Remarks:
217
-            *  - When == 0, the encoder may or may not use LTRs during encoding.
218
-            *  - When >0, the user has control over all LTR.
219
-            *  - With user control of LTR, B-pictures and Intra-refresh features are not supported.
220
-            *  - The actual maximum number of LTRs allowed depends on H.264 Annex A Table A-1 Level limits, which defines dependencies between the H.264 Level number, encoding resolution, and DPB size. The DPB size limit impacts the maximum number of LTR allowed.
221
-            **/
222
-           void SetMaximumLongTermReferenceFrames(uint32_t maximumLTRFrames);  // Long-Term Reference Frames. If 0, Encoder decides, if non-0 B-Pictures and Intra-Refresh are not supported.
223
-           uint32_t GetMaximumLongTermReferenceFrames();
224
-
225
-           /* Coding Type */
226
-           void SetCodingType(VCECodingType type);
227
-           VCECodingType GetCodingType();
228
-
229
-           /************************************************************************/
230
-           /* Frame Properties                                                     */
231
-           /************************************************************************/
232
-
233
-           void SetColorProfile(VCEColorProfile profile);
234
-           VCEColorProfile GetColorProfile();
235
-
236
-           void SetFullColorRangeEnabled(bool enabled);
237
-           bool IsFullColorRangeEnabled();
238
-
239
-           /* Selects progressive or interlaced scan
240
-           * Static Property, changes cause a restart. */
241
-           void SetScanType(VCEScanType scanType);
242
-           VCEScanType GetScanType();
243
-
244
-           /*  Output Resolution */
245
-           void SetFrameSize(uint32_t width, uint32_t height);
246
-           std::pair<uint32_t, uint32_t> GetFrameSize();
247
-
248
-           /*  Sets the Frame Rate numerator and denumerator */
249
-           void SetFrameRate(uint32_t num, uint32_t den);
250
-           std::pair<uint32_t, uint32_t> GetFrameRate();
251
-
252
-           /************************************************************************/
253
-           /* Rate Control Properties                                              */
254
-           /************************************************************************/
255
-           
256
-           /*  Selects the rate control method:
257
-           *   - CQP - Constrained QP,
258
-           *   - CBR - Constant Bitrate,
259
-           *   - VBR - Peak Constrained VBR,
260
-           *   - VBR_LAT - Latency Constrained VBR
261
-           *
262
-           *   Remarks:
263
-           *   - 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].
264
-           *   - 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-pictures).
265
-           **/
266
-           void SetRateControlMethod(VCERateControlMethod method);
267
-           VCERateControlMethod GetRateControlMethod();
268
-
269
-           /*  Sets the target bitrate */
270
-           void SetTargetBitrate(uint32_t bitrate);
271
-           uint32_t GetTargetBitrate();
272
-
273
-           /*  Sets the peak bitrate */
274
-           void SetPeakBitrate(uint32_t bitrate);
275
-           uint32_t GetPeakBitrate();
276
-
277
-           /*  Sets the minimum QP */
278
-           void SetMinimumQP(uint8_t qp);
279
-           uint8_t GetMinimumQP();
280
-
281
-           /*  Sets the maximum QP */
282
-           void SetMaximumQP(uint8_t qp);
283
-           uint8_t GetMaximumQP();
284
-
285
-           /*  Sets the Constant QP for I-Pictures.
286
-           *
287
-           *   Remarks:
288
-           *   - Only available for CQP rate control method.
289
-           **/
290
-           void SetIFrameQP(uint8_t qp);
291
-           uint8_t GetIFrameQP();
292
-
293
-           /*  Sets the Constant QP for P-Pictures.
294
-           *
295
-           *   Remarks:
296
-           *   - Only available for CQP rate control method.
297
-           **/
298
-           void SetPFrameQP(uint8_t qp);
299
-           uint8_t GetPFrameQP();
300
-
301
-           /*  Sets the Constant QP for B-Pictures.
302
-           *
303
-           *   Remarks:
304
-           *   - Only available for CQP rate control method.
305
-           **/
306
-           void SetBFrameQP(uint8_t qp);
307
-           uint8_t GetBFrameQP();
308
-
309
-           /* Selects the delta QP of non-reference B-Pictures with respect to I pictures */
310
-           void SetBPictureDeltaQP(int8_t qp);
311
-           int8_t GetBPictureDeltaQP();
312
-
313
-           /* Selects delta QP of reference B-Pictures with respect to I pictures */
314
-           void SetReferenceBPictureDeltaQP(int8_t qp);
315
-           int8_t GetReferenceBPictureDeltaQP();
316
-
317
-           /*  Sets the VBV Buffer Size in bits */
318
-           void SetVBVBufferSize(uint32_t size);
319
-           void SetVBVBufferAutomatic(double_t strictness);
320
-           uint32_t GetVBVBufferSize();
321
-
322
-           /*  Sets the initial VBV Buffer Fullness */
323
-           void SetInitialVBVBufferFullness(double_t fullness);
324
-           double_t GetInitialVBVBufferFullness();
325
-
326
-           /*  Sets Maximum AU Size in bits */
327
-           void SetMaximumAccessUnitSize(uint32_t size);
328
-           uint32_t GetMaximumAccessUnitSize();
329
-
330
-           /*  Enables/Disables filler data */
331
-           void SetFillerDataEnabled(bool enabled);
332
-           bool IsFillerDataEnabled();
333
-
334
-           /*  Enables skip frame for rate control */
335
-           void SetFrameSkippingEnabled(bool enabled);
336
-           bool IsFrameSkippingEnabled();
337
-
338
-           /*  Enables/Disables constraints on QP variation within a picture to meet HRD requirement(s) */
339
-           void SetEnforceHRDRestrictionsEnabled(bool enforce);
340
-           bool IsEnforceHRDRestrictionsEnabled();
341
-
342
-           /************************************************************************/
343
-           /* Picture Control Properties                                           */
344
-           /************************************************************************/
345
-
346
-           /*  Sets IDR period. IDRPeriod= 0 turns IDR off */
347
-           void SetIDRPeriod(uint32_t period);
348
-           uint32_t GetIDRPeriod();
349
-
350
-           /*  Sets the headers insertion spacing */
351
-           void SetHeaderInsertionSpacing(uint32_t spacing); // Similar to IDR Period, spacing (in frames) between headers.
352
-           uint32_t GetHeaderInsertionSpacing();
353
-
354
-           /*  Sets the number of consecutive B-pictures in a GOP. BPicturesPattern = 0 indicates that B-pictures are not used */
355
-           void SetBPicturePattern(VCEBPicturePattern pattern);
356
-           VCEBPicturePattern GetBPicturePattern();
357
-
358
-           /*  Enables or disables using B-pictures as references */
359
-           void SetBPictureReferenceEnabled(bool enabled);
360
-           bool IsBPictureReferenceEnabled();
361
-
362
-           /*  Turns on/off the Deblocking Filter */
363
-           void SetDeblockingFilterEnabled(bool enabled);
364
-           bool IsDeblockingFilterEnabled();
365
-
366
-           /*  Sets the number of slices per frame */
367
-           void SetSlicesPerFrame(uint32_t slices);
368
-           uint32_t GetSlicesPerFrame();
369
-
370
-           /*  Sets the number of intra-refresh macro-blocks per slot */
371
-           void SetIntraRefreshMBsNumberPerSlot(uint32_t mbs);
372
-           uint32_t GetIntraRefreshMBsNumberPerSlot();
373
-
374
-           /************************************************************************/
375
-           /* Miscellaneous Control Properties                                     */
376
-           /************************************************************************/
377
-           
378
-           /* Turns on/off half-pixel motion estimation */
379
-           void SetHalfPixelMotionEstimationEnabled(bool enabled);
380
-           bool IsHalfPixelMotionEstimationEnabled();
381
-
382
-           /* Turns on/off quarter-pixel motion estimation */
383
-           void SetQuarterPixelMotionEstimationEnabled(bool enabled);
384
-           bool IsQuarterPixelMotionEstimationEnabled();
385
-
386
-           /************************************************************************/
387
-           /* Hidden Properties                                                    */
388
-           /************************************************************************/
389
-           
390
-           void SetGOPSize(uint32_t gopSize);
391
-           uint32_t GetGOPSize();
392
-
393
-           void SetWaitForTaskEnabled(bool enabled);
394
-           bool IsWaitForTaskEnabled();
395
-
396
-           void SetAspectRatio(uint32_t x, uint32_t y);
397
-           std::pair<uint32_t, uint32_t> GetAspectRatio();
398
-
399
-           void SetMaximumNumberOfReferenceFrames(uint32_t frameCount);
400
-           uint32_t GetMaximumNumberOfReferenceFrames();
401
-
402
-           uint32_t GetMaxMBPerSec();
403
-
404
-           void SetInstanceID(uint32_t instanceId);
405
-           uint32_t GetInstanceID();
406
-
407
-           void SetVBAQEnabled(bool enabled);
408
-           bool IsVBAQEnabled();
409
-
410
-           void SetRateControlPreanalysisEnabled(bool enabled);
411
-           bool IsRateControlPreanalysisEnabled();
412
-
413
-           void SetIntraRefreshNumberOfStripes(uint32_t stripes); // 0 - INT_MAX
414
-           uint32_t GetIntraRefreshNumberOfStripes();
415
-
416
-           void SetSliceMode(uint32_t mode); // 1 or 2
417
-           uint32_t GetSliceMode();
418
-
419
-           void SetMaximumSliceSize(uint32_t size); // 0 - INT_MAX
420
-           uint32_t GetMaximumSliceSize();
421
-
422
-           // - SliceControlMode: AMF_VIDEO_ENCODER_SLICE_CTRL_MODE_MB_ROW, AMF_VIDEO_ENCODER_SLICE_CTRL_MODE_MB
423
-           void SetSliceControlMode(uint32_t mode); // 0, 1, 2, 3
424
-           uint32_t GetSliceControlMode();
425
-
426
-           void SetSliceControlSize(uint32_t size); // 0 - INT_MAX
427
-           uint32_t GetSliceControlSize();
428
-
429
-           // HEVC Parameters
430
-           // - MinQP_I, MaxQP_I
431
-           // - MinQP_P, MaxQP_P
432
-           // - QPCBOFFSET, QPCROFFSET
433
-           // - GOPPerIDR
434
-           // - GOPSizeMin, GOPSizeMax
435
-           // - EnableGOPAlignment
436
-
437
-           #pragma endregion Methods
438
-           //////////////////////////////////////////////////////////////////////////
439
-
440
-           //////////////////////////////////////////////////////////////////////////
441
-           #pragma region Members
442
-           //////////////////////////////////////////////////////////////////////////
443
-           private:
444
-
445
-           // AMF Data References
446
-           std::shared_ptr<Plugin::AMD::AMF> m_AMF;
447
-           amf::AMFFactory* m_AMFFactory;
448
-           amf::AMFContextPtr m_AMFContext;
449
-           amf::AMFComponentPtr m_AMFConverter;
450
-           amf::AMFComponentPtr m_AMFEncoder;
451
-           amf::AMFComputePtr m_AMFCompute;
452
-
453
-           // API References
454
-           std::unique_ptr<Plugin::API::APIBase> m_APIDevice;
455
-
456
-           // Static Buffers
457
-           std::vector<uint8_t> m_PacketDataBuffer;
458
-           std::vector<uint8_t> m_ExtraDataBuffer;
459
-
460
-           // Structured Queue
461
-           struct {
462
-               std::queue<amf::AMFSurfacePtr> queue;
463
-
464
-               // Threading
465
-               std::thread thread;
466
-               std::mutex mutex;
467
-               std::condition_variable condvar;
468
-               std::mutex queuemutex;
469
-           } m_Input;
470
-           struct {
471
-               std::queue<amf::AMFDataPtr> queue;
472
-
473
-               // Threading
474
-               std::thread thread;
475
-               std::mutex mutex;
476
-               std::condition_variable condvar;
477
-               std::mutex queuemutex;
478
-           } m_Output;
479
-
480
-           // Internal Properties
481
-           VCEEncoderType m_EncoderType;
482
-           VCEMemoryType m_MemoryType;
483
-           bool m_UseOpenCL;
484
-           VCEColorFormat m_SurfaceFormat;
485
-           bool m_Flag_IsStarted,
486
-               m_Flag_FirstFrameSubmitted,
487
-               m_Flag_FirstFrameReceived;
488
-           std::pair<uint32_t, uint32_t> m_FrameSize,
489
-               m_FrameRate;
490
-           double_t m_FrameRateDivisor,
491
-               m_FrameRateReverseDivisor;
492
-           size_t m_InputQueueLimit,
493
-               m_InputQueueLastSize;
494
-           uint32_t m_TimerPeriod;
495
-           VCEColorProfile m_ColorProfile;
496
-           
497
-           #pragma endregion Members
498
-           //////////////////////////////////////////////////////////////////////////
499
-       };
500
-   }
501
-}
502
\ No newline at end of file
503
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Source/amd-amf-vce-capabilities.cpp Deleted
366
 
1
@@ -1,364 +0,0 @@
2
-/*
3
-MIT License
4
-
5
-Copyright (c) 2016 Michael Fabian Dirks
6
-
7
-Permission is hereby granted, free of charge, to any person obtaining a copy
8
-of this software and associated documentation files (the "Software"), to deal
9
-in the Software without restriction, including without limitation the rights
10
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
-copies of the Software, and to permit persons to whom the Software is
12
-furnished to do so, subject to the following conditions:
13
-
14
-The above copyright notice and this permission notice shall be included in all
15
-copies or substantial portions of the Software.
16
-
17
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
-SOFTWARE.
24
-*/
25
-
26
-#pragma once
27
-
28
-//////////////////////////////////////////////////////////////////////////
29
-// Includes
30
-//////////////////////////////////////////////////////////////////////////
31
-#include <string>
32
-#include <sstream>
33
-
34
-#ifdef _WIN32
35
-#include <windows.h>
36
-#include <VersionHelpers.h>
37
-#endif
38
-
39
-#include "amd-amf-vce-capabilities.h"
40
-#include "api-d3d11.h"
41
-#include "api-d3d9.h"
42
-#include "misc-util.cpp"
43
-
44
-//////////////////////////////////////////////////////////////////////////
45
-// Code
46
-//////////////////////////////////////////////////////////////////////////
47
-
48
-std::shared_ptr<Plugin::AMD::VCECapabilities> Plugin::AMD::VCECapabilities::GetInstance() {
49
-   static std::shared_ptr<VCECapabilities> __instance = std::make_shared<VCECapabilities>();
50
-   static std::mutex __mutex;
51
-
52
-   const std::lock_guard<std::mutex> lock(__mutex);
53
-   return __instance;
54
-}
55
-
56
-void Plugin::AMD::VCECapabilities::ReportCapabilities() {
57
-   auto inst = GetInstance();
58
-
59
-   auto devs = inst->GetDevices();
60
-   for (auto dev : devs) {
61
-       ReportDeviceCapabilities(dev);
62
-   }
63
-}
64
-
65
-void Plugin::AMD::VCECapabilities::ReportDeviceCapabilities(Plugin::API::Device device) {
66
-   auto inst = GetInstance();
67
-
68
-   AMF_LOG_INFO("Capabilities for Device '%s':", device.Name.c_str());
69
-
70
-   VCEEncoderType types[] = { VCEEncoderType_AVC, VCEEncoderType_SVC };
71
-   for (VCEEncoderType type : types) {
72
-       auto caps = inst->GetDeviceCaps(device, type);
73
-
74
-       AMF_LOG_INFO("  %s (Acceleration: %s)",
75
-           (type == VCEEncoderType_AVC ? "AVC" : (type == VCEEncoderType_SVC ? "SVC" : (type == VCEEncoderType_HEVC ? "HEVC" : "Unknown"))),
76
-           (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")))
77
-       );
78
-
79
-       if (caps.acceleration_type == amf::AMF_ACCEL_NOT_SUPPORTED)
80
-           continue;
81
-
82
-       AMF_LOG_INFO("    Limits");
83
-       AMF_LOG_INFO("      # of Streams: %ld", caps.maxNumOfStreams);
84
-       AMF_LOG_INFO("      # of Instances: %ld", caps.maxNumOfHwInstances);
85
-       AMF_LOG_INFO("      Profile: %s", Plugin::Utility::ProfileAsString((VCEProfile)caps.maxProfile));
86
-       AMF_LOG_INFO("      Level: %ld.%ld", caps.maxProfileLevel / 10, caps.maxProfileLevel % 10);
87
-       AMF_LOG_INFO("      Bitrate: %ld", caps.maxBitrate);
88
-       AMF_LOG_INFO("      Temporal Layers: %ld", caps.maxTemporalLayers);
89
-       AMF_LOG_INFO("      Reference Frames: %ld (min) - %ld (max)", caps.minReferenceFrames, caps.maxReferenceFrames);
90
-       AMF_LOG_INFO("    Features")
91
-           AMF_LOG_INFO("      B-Frames: %s", caps.supportsBFrames ? "Supported" : "Not Supported");
92
-       AMF_LOG_INFO("      Fixed Slice Mode: %s", caps.supportsFixedSliceMode ? "Supported" : "Not Supported");
93
-       AMF_LOG_INFO("    Input");
94
-       ReportDeviceIOCapabilities(device, type, false);
95
-       AMF_LOG_INFO("    Output");
96
-       ReportDeviceIOCapabilities(device, type, true);
97
-   }
98
-}
99
-
100
-void Plugin::AMD::VCECapabilities::ReportDeviceIOCapabilities(Plugin::API::Device device, VCEEncoderType type, bool output) {
101
-   auto amf = Plugin::AMD::AMF::GetInstance();
102
-   auto inst = GetInstance();
103
-   auto ioCaps = inst->GetDeviceIOCaps(device, type, output);
104
-   AMF_LOG_INFO("      Resolution: %ldx%ld - %ldx%ld",
105
-       ioCaps.minWidth, ioCaps.minHeight,
106
-       ioCaps.maxWidth, ioCaps.maxHeight);
107
-   AMF_LOG_INFO("      Vertical Alignment: %ld", ioCaps.verticalAlignment);
108
-   AMF_LOG_INFO("      Interlaced: %s", ioCaps.isInterlacedSupported ? "Supported" : "Not Supported");
109
-   std::stringstream formatstr;
110
-   for (auto format : ioCaps.formats) {
111
-       std::vector<char> buf(1024);
112
-       wcstombs(buf.data(), amf->GetTrace()->SurfaceGetFormatName(format.first), 1024);
113
-       formatstr
114
-           << buf.data()
115
-           << (format.second ? " (Native)" : "")
116
-           << ", ";
117
-   }
118
-   AMF_LOG_INFO("      Formats: %s", formatstr.str().c_str());
119
-   std::stringstream memorystr;
120
-   for (auto memory : ioCaps.memoryTypes) {
121
-       std::vector<char> buf(1024);
122
-       wcstombs(buf.data(), amf->GetTrace()->GetMemoryTypeName(memory.first), 1024);
123
-       memorystr
124
-           << buf.data()
125
-           << (memory.second ? " (Native)" : "")
126
-           << ", ";
127
-   }
128
-   AMF_LOG_INFO("      Memory Types: %s", memorystr.str().c_str());
129
-}
130
-
131
-Plugin::AMD::VCECapabilities::VCECapabilities() {
132
-   this->Refresh();
133
-}
134
-
135
-Plugin::AMD::VCECapabilities::~VCECapabilities() {}
136
-
137
-static AMF_RESULT GetIOCapability(bool output, amf::AMFCapsPtr amfCaps, Plugin::AMD::VCEDeviceCapabilities::IOCaps* caps) {
138
-   AMF_RESULT res = AMF_OK;
139
-   amf::AMFIOCapsPtr amfIOCaps;
140
-   if (output)
141
-       res = amfCaps->GetOutputCaps(&amfIOCaps);
142
-   else
143
-       res = amfCaps->GetInputCaps(&amfIOCaps);
144
-   if (res != AMF_OK)
145
-       return res;
146
-
147
-   amfIOCaps->GetWidthRange(&(caps->minWidth), &(caps->maxWidth));
148
-   amfIOCaps->GetHeightRange(&(caps->minHeight), &(caps->maxHeight));
149
-   caps->isInterlacedSupported = amfIOCaps->IsInterlacedSupported();
150
-   caps->verticalAlignment = amfIOCaps->GetVertAlign();
151
-
152
-   int32_t numFormats = amfIOCaps->GetNumOfFormats();
153
-   caps->formats.resize(numFormats);
154
-   for (int32_t formatIndex = 0; formatIndex < numFormats; formatIndex++) {
155
-       amf::AMF_SURFACE_FORMAT format = amf::AMF_SURFACE_UNKNOWN;
156
-       bool isNative = false;
157
-
158
-       amfIOCaps->GetFormatAt(formatIndex, &format, &isNative);
159
-       caps->formats[formatIndex].first = format;
160
-       caps->formats[formatIndex].second = isNative;
161
-   }
162
-
163
-   int32_t numMemoryTypes = amfIOCaps->GetNumOfMemoryTypes();
164
-   caps->memoryTypes.resize(numMemoryTypes);
165
-   for (int32_t memoryTypeIndex = 0; memoryTypeIndex < numMemoryTypes; memoryTypeIndex++) {
166
-       amf::AMF_MEMORY_TYPE type = amf::AMF_MEMORY_UNKNOWN;
167
-       bool isNative = false;
168
-
169
-       amfIOCaps->GetMemoryTypeAt(memoryTypeIndex, &type, &isNative);
170
-       caps->memoryTypes[memoryTypeIndex].first = type;
171
-       caps->memoryTypes[memoryTypeIndex].second = isNative;
172
-   }
173
-
174
-   return AMF_OK;
175
-}
176
-
177
-bool Plugin::AMD::VCECapabilities::Refresh() {
178
-   AMF_RESULT res;
179
-
180
-   // Build a list of Devices
181
-   #ifdef _WIN32
182
-   if (IsWindows8OrGreater()) {
183
-       devices = Plugin::API::Direct3D11::EnumerateDevices();
184
-   } else if (IsWindowsXPOrGreater()) {
185
-       devices = Plugin::API::Direct3D9::EnumerateDevices();
186
-   } else
187
-       #endif 
188
-   { // OpenGL
189
-       //devices = Plugin::API::OpenGL::EnumerateDevices();
190
-   }
191
-   //devices.insert(devices.begin(), Plugin::API::Device());
192
-
193
-   // Query Information for each Device
194
-   std::shared_ptr<AMD::AMF> amfInstance = AMD::AMF::GetInstance();
195
-   amf::AMFFactory* amfFactory = amfInstance->GetFactory();
196
-   for (Plugin::API::Device device : devices) {
197
-       amf::AMFContextPtr amfContext;
198
-       res = amfFactory->CreateContext(&amfContext);
199
-       if (res != AMF_OK) {
200
-           AMF_LOG_ERROR("Unable to gather capabilities for device '%s', error %ls (code %d).",
201
-               device.Name.c_str(), amfInstance->GetTrace()->GetResultText(res), res);
202
-           continue;
203
-       }
204
-
205
-       auto apiDev = Plugin::API::APIBase::CreateBestAvailableAPI(device);
206
-       switch (apiDev->GetType()) {
207
-           case Plugin::API::APIType_Direct3D11:
208
-               res = amfContext->InitDX11(apiDev->GetContext());
209
-               break;
210
-           case Plugin::API::APIType_Direct3D9:
211
-               res = amfContext->InitDX9(apiDev->GetContext());
212
-               break;
213
-           case Plugin::API::APIType_OpenGL:
214
-               res = amfContext->InitOpenGL(apiDev->GetContext(), nullptr, nullptr);
215
-               break;
216
-       }
217
-       if (res != AMF_OK) {
218
-           AMF_LOG_ERROR("Unable to gather capabilities for device '%s' after initialization, error %ls (code %d).",
219
-               device.Name.c_str(), amfInstance->GetTrace()->GetResultText(res), res);
220
-           continue;
221
-       }
222
-
223
-       VCEDeviceCapabilities devAVCCaps, devSVCCaps;
224
-       const wchar_t* capsString[] = {
225
-           AMFVideoEncoderVCE_AVC,
226
-           AMFVideoEncoderVCE_SVC,
227
-       };
228
-       VCEDeviceCapabilities* caps[] = {
229
-           &devAVCCaps,
230
-           &devSVCCaps,
231
-       };
232
-       VCEEncoderType capsType[] = {
233
-           VCEEncoderType_AVC,
234
-           VCEEncoderType_SVC,
235
-       };
236
-
237
-       for (uint8_t capsIndex = 0; capsIndex < _countof(caps); capsIndex++) {
238
-           #pragma region Null Structure
239
-           caps[capsIndex]->acceleration_type = amf::AMF_ACCEL_NOT_SUPPORTED;
240
-           caps[capsIndex]->maxBitrate =
241
-               caps[capsIndex]->maxNumOfStreams =
242
-               caps[capsIndex]->maxProfile =
243
-               caps[capsIndex]->maxProfileLevel =
244
-               caps[capsIndex]->minReferenceFrames =
245
-               caps[capsIndex]->maxReferenceFrames =
246
-               caps[capsIndex]->maxTemporalLayers =
247
-               caps[capsIndex]->maxNumOfHwInstances =
248
-               caps[capsIndex]->input.minWidth =
249
-               caps[capsIndex]->input.maxWidth =
250
-               caps[capsIndex]->input.minHeight =
251
-               caps[capsIndex]->input.maxHeight =
252
-               caps[capsIndex]->input.verticalAlignment =
253
-               caps[capsIndex]->output.minWidth =
254
-               caps[capsIndex]->output.maxWidth =
255
-               caps[capsIndex]->output.minHeight =
256
-               caps[capsIndex]->output.maxHeight =
257
-               caps[capsIndex]->output.verticalAlignment = 0;
258
-           caps[capsIndex]->supportsBFrames =
259
-               caps[capsIndex]->supportsFixedSliceMode =
260
-               caps[capsIndex]->input.isInterlacedSupported =
261
-               caps[capsIndex]->output.isInterlacedSupported = false;
262
-           caps[capsIndex]->input.formats.clear();
263
-           caps[capsIndex]->output.formats.clear();
264
-           caps[capsIndex]->input.memoryTypes.clear();
265
-           caps[capsIndex]->output.memoryTypes.clear();
266
-           #pragma endregion Null Structure
267
-
268
-           #pragma region Initialization
269
-           amf::AMFComponentPtr amfComponent;
270
-           res = amfFactory->CreateComponent(amfContext, capsString[capsIndex], &amfComponent);
271
-           if (res != AMF_OK) {
272
-               AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Failed to create component for device '%s' with codec '%ls', error %ls (code %d).",
273
-                   device.Name.c_str(), capsString[capsIndex],
274
-                   amfInstance->GetTrace()->GetResultText(res), res);
275
-               continue;
276
-           }
277
-
278
-           amf::AMFCapsPtr amfCaps;
279
-           res = amfComponent->GetCaps(&amfCaps);
280
-           if (res != AMF_OK) {
281
-               AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Failed to gather capabilities for device '%s' with codec '%ls', error %ls (code %d).",
282
-                   device.Name.c_str(), capsString[capsIndex],
283
-                   amfInstance->GetTrace()->GetResultText(res), res);
284
-               amfComponent->Terminate();
285
-               continue;
286
-           }
287
-           #pragma endregion Initialization
288
-
289
-           #pragma region Basic Capabilities
290
-           caps[capsIndex]->acceleration_type = amfCaps->GetAccelerationType();
291
-           amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_MAX_BITRATE, &(caps[capsIndex]->maxBitrate));
292
-           amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_NUM_OF_STREAMS, &(caps[capsIndex]->maxNumOfStreams));
293
-           amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_MAX_PROFILE, &(caps[capsIndex]->maxProfile));
294
-           amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_MAX_LEVEL, &(caps[capsIndex]->maxProfileLevel));
295
-           amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_BFRAMES, &(caps[capsIndex]->supportsBFrames));
296
-           amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_MIN_REFERENCE_FRAMES, &(caps[capsIndex]->minReferenceFrames));
297
-           amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_MAX_REFERENCE_FRAMES, &(caps[capsIndex]->maxReferenceFrames));
298
-           amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_MAX_TEMPORAL_LAYERS, &(caps[capsIndex]->maxTemporalLayers));
299
-           amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_FIXED_SLICE_MODE, &(caps[capsIndex]->supportsFixedSliceMode));
300
-           amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_NUM_OF_HW_INSTANCES, &(caps[capsIndex]->maxNumOfHwInstances));
301
-           #pragma endregion Basic Capabilities
302
-
303
-           if (GetIOCapability(false, amfCaps, &(caps[capsIndex]->input))) {
304
-               AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Failed to gather input capabilities for device '%s' with codec '%ls', error %ls (code %d).",
305
-                   device.Name.c_str(), capsString[capsIndex],
306
-                   amfInstance->GetTrace()->GetResultText(res), res);
307
-           }
308
-           if (GetIOCapability(true, amfCaps, &(caps[capsIndex]->output))) {
309
-               AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Failed to gather output capabilities for device '%s' with codec '%ls', error %ls (code %d).",
310
-                   device.Name.c_str(), capsString[capsIndex],
311
-                   amfInstance->GetTrace()->GetResultText(res), res);
312
-           }
313
-
314
-           amfComponent->Terminate();
315
-
316
-           // Register
317
-           std::pair<Plugin::API::Device, Plugin::AMD::VCEEncoderType> devkv(device, capsType[capsIndex]);
318
-           deviceToCapabilities.insert(std::make_pair(devkv, *caps[capsIndex]));
319
-       }
320
-
321
-       amfContext->Terminate();
322
-   }
323
-
324
-   return true;
325
-}
326
-
327
-std::vector<Plugin::API::Device> Plugin::AMD::VCECapabilities::GetDevices() {
328
-   return std::vector<Plugin::API::Device>(devices);
329
-}
330
-
331
-Plugin::AMD::VCEDeviceCapabilities Plugin::AMD::VCECapabilities::GetDeviceCaps(Plugin::API::Device device, VCEEncoderType type) {
332
-   if (deviceToCapabilities.empty())
333
-       return Plugin::AMD::VCEDeviceCapabilities();
334
-
335
-   if (device.UniqueId == "")
336
-       return deviceToCapabilities.begin()->second;
337
-
338
-   auto dt = std::pair<Plugin::API::Device, Plugin::AMD::VCEEncoderType>(device, type);
339
-   if (deviceToCapabilities.count(dt) == 0)
340
-       return Plugin::AMD::VCEDeviceCapabilities();
341
-
342
-   return deviceToCapabilities.find(dt)->second;
343
-}
344
-
345
-Plugin::AMD::VCEDeviceCapabilities::IOCaps Plugin::AMD::VCECapabilities::GetDeviceIOCaps(Plugin::API::Device device, VCEEncoderType type, bool output) {
346
-   if (deviceToCapabilities.empty())
347
-       return Plugin::AMD::VCEDeviceCapabilities::IOCaps();
348
-
349
-   if (device.UniqueId == "") {
350
-       if (output)
351
-           return deviceToCapabilities.begin()->second.output;
352
-       else
353
-           return deviceToCapabilities.begin()->second.input;
354
-   }
355
-
356
-   auto dt = std::pair<Plugin::API::Device, Plugin::AMD::VCEEncoderType>(device, type);
357
-   if (deviceToCapabilities.count(dt) == 0)
358
-       return Plugin::AMD::VCEDeviceCapabilities::IOCaps();
359
-
360
-   if (output)
361
-       return deviceToCapabilities.find(dt)->second.output;
362
-   else
363
-       return deviceToCapabilities.find(dt)->second.input;
364
-}
365
-
366
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Source/amd-amf-vce.cpp Deleted
1870
 
1
@@ -1,1868 +0,0 @@
2
-/*
3
-MIT License
4
-
5
-Copyright (c) 2016 Michael Fabian Dirks
6
-
7
-Permission is hereby granted, free of charge, to any person obtaining a copy
8
-of this software and associated documentation files (the "Software"), to deal
9
-in the Software without restriction, including without limitation the rights
10
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
-copies of the Software, and to permit persons to whom the Software is
12
-furnished to do so, subject to the following conditions:
13
-
14
-The above copyright notice and this permission notice shall be included in all
15
-copies or substantial portions of the Software.
16
-
17
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
-SOFTWARE.
24
-*/
25
-
26
-//////////////////////////////////////////////////////////////////////////
27
-// Includes
28
-//////////////////////////////////////////////////////////////////////////
29
-#include <chrono>
30
-
31
-#include "amd-amf-vce.h"
32
-#include "amd-amf-vce-capabilities.h"
33
-#include "misc-util.cpp"
34
-
35
-// AMF
36
-#include "components/VideoEncoderVCE.h"
37
-#include "components/VideoConverter.h"
38
-
39
-// Windows
40
-#ifdef _WIN32
41
-#include <windows.h>
42
-#include <VersionHelpers.h>
43
-
44
-#include "api-d3d9.h"
45
-#include "api-d3d11.h"
46
-#endif
47
-
48
-//////////////////////////////////////////////////////////////////////////
49
-// Code
50
-//////////////////////////////////////////////////////////////////////////
51
-
52
-// Logging and Exception Helpers
53
-static void FormatTextWithAMFError(std::vector<char>* buffer, const char* format, AMF_RESULT res) {
54
-   sprintf(buffer->data(), format, Plugin::AMD::AMF::GetInstance()->GetTrace()->GetResultText(res), res);
55
-}
56
-
57
-template<typename _T>
58
-static void FormatTextWithAMFError(std::vector<char>* buffer, const char* format, _T other, AMF_RESULT res) {
59
-   sprintf(buffer->data(), format, other, Plugin::AMD::AMF::GetInstance()->GetTrace()->GetResultText(res), res);
60
-}
61
-
62
-// Class
63
-void Plugin::AMD::VCEEncoder::InputThreadMain(Plugin::AMD::VCEEncoder* p_this) {
64
-   p_this->InputThreadLogic();
65
-}
66
-
67
-void Plugin::AMD::VCEEncoder::OutputThreadMain(Plugin::AMD::VCEEncoder* p_this) {
68
-   p_this->OutputThreadLogic();
69
-}
70
-
71
-static void fastPrintVariant(const char* text, amf::AMFVariantStruct variant) {
72
-   std::vector<char> buf(1024);
73
-   switch (variant.type) {
74
-       case amf::AMF_VARIANT_EMPTY:
75
-           sprintf(buf.data(), "%s%s", text, "Empty");
76
-           break;
77
-       case amf::AMF_VARIANT_BOOL:
78
-           sprintf(buf.data(), "%s%s", text, variant.boolValue ? "true" : "false");
79
-           break;
80
-       case amf::AMF_VARIANT_INT64:
81
-           sprintf(buf.data(), "%s%lld", text, variant.int64Value);
82
-           break;
83
-       case amf::AMF_VARIANT_DOUBLE:
84
-           sprintf(buf.data(), "%s%f", text, variant.doubleValue);
85
-           break;
86
-       case amf::AMF_VARIANT_RECT:
87
-           sprintf(buf.data(), "%s[%ld,%ld,%ld,%ld]", text,
88
-               variant.rectValue.top, variant.rectValue.left,
89
-               variant.rectValue.bottom, variant.rectValue.right);
90
-           break;
91
-       case amf::AMF_VARIANT_SIZE:
92
-           sprintf(buf.data(), "%s%ldx%ld", text,
93
-               variant.sizeValue.width, variant.sizeValue.height);
94
-           break;
95
-       case amf::AMF_VARIANT_POINT:
96
-           sprintf(buf.data(), "%s[%ld,%ld]", text,
97
-               variant.pointValue.x, variant.pointValue.y);
98
-           break;
99
-       case amf::AMF_VARIANT_RATE:
100
-           sprintf(buf.data(), "%s%ld/%ld", text,
101
-               variant.rateValue.num, variant.rateValue.den);
102
-           break;
103
-       case amf::AMF_VARIANT_RATIO:
104
-           sprintf(buf.data(), "%s%ld:%ld", text,
105
-               variant.ratioValue.num, variant.ratioValue.den);
106
-           break;
107
-       case amf::AMF_VARIANT_COLOR:
108
-           sprintf(buf.data(), "%s(%d,%d,%d,%d)", text,
109
-               variant.colorValue.r,
110
-               variant.colorValue.g,
111
-               variant.colorValue.b,
112
-               variant.colorValue.a);
113
-           break;
114
-       case amf::AMF_VARIANT_STRING:
115
-           sprintf(buf.data(), "%s'%s'", text,
116
-               variant.stringValue);
117
-           break;
118
-       case amf::AMF_VARIANT_WSTRING:
119
-           sprintf(buf.data(), "%s'%ls'", text,
120
-               variant.wstringValue);
121
-           break;
122
-   }
123
-   AMF_LOG_INFO("%s", buf.data());
124
-};
125
-
126
-static void printDebugInfo(amf::AMFComponentPtr m_AMFEncoder) {
127
-   #ifdef _DEBUG
128
-   amf::AMFPropertyInfo* pInfo;
129
-   size_t propCount = m_AMFEncoder->GetPropertyCount();
130
-   AMF_LOG_INFO("-- Internal AMF Encoder Properties --");
131
-   for (size_t propIndex = 0; propIndex < propCount; propIndex++) {
132
-       static const char* typeToString[] = {
133
-           "Empty",
134
-           "Boolean",
135
-           "Int64",
136
-           "Double",
137
-           "Rect",
138
-           "Size",
139
-           "Point",
140
-           "Rate",
141
-           "Ratio",
142
-           "Color",
143
-           "String",
144
-           "WString",
145
-           "Interface"
146
-       };
147
-
148
-       AMF_RESULT res = m_AMFEncoder->GetPropertyInfo(propIndex, (const amf::AMFPropertyInfo**) &pInfo);
149
-       if (res != AMF_OK)
150
-           continue;
151
-       AMF_LOG_INFO(" [%ls] %ls (Type: %s, Index %d)",
152
-           pInfo->name, pInfo->desc, typeToString[pInfo->type], propIndex);
153
-       AMF_LOG_INFO("  Content Type: %d",
154
-           pInfo->contentType);
155
-       AMF_LOG_INFO("  Access: %s%s%s",
156
-           (pInfo->accessType & amf::AMF_PROPERTY_ACCESS_READ) ? "R" : "",
157
-           (pInfo->accessType & amf::AMF_PROPERTY_ACCESS_WRITE) ? "W" : "",
158
-           (pInfo->accessType & amf::AMF_PROPERTY_ACCESS_WRITE_RUNTIME) ? "X" : "");
159
-
160
-       AMF_LOG_INFO("  Values:");
161
-       amf::AMFVariantStruct curStruct = amf::AMFVariantStruct();
162
-       m_AMFEncoder->GetProperty(pInfo->name, &curStruct);
163
-       fastPrintVariant("    Current: ", curStruct);
164
-       fastPrintVariant("    Default: ", pInfo->defaultValue);
165
-       fastPrintVariant("    Minimum: ", pInfo->minValue);
166
-       fastPrintVariant("    Maximum: ", pInfo->maxValue);
167
-       if (pInfo->pEnumDescription) {
168
-           AMF_LOG_INFO("  Enumeration: ");
169
-           const amf::AMFEnumDescriptionEntry* pEnumEntry = pInfo->pEnumDescription;
170
-           while (pEnumEntry->name != nullptr) {
171
-               AMF_LOG_INFO("    %ls (%ld)",
172
-                   pEnumEntry->name,
173
-                   pEnumEntry->value);
174
-               pEnumEntry++;
175
-           }
176
-       }
177
-   }
178
-   #endif
179
-}
180
-
181
-Plugin::AMD::VCEEncoder::VCEEncoder(VCEEncoderType p_Type,
182
-   std::string p_DeviceId/* = ""*/,
183
-   bool p_OpenCL/* = false*/,
184
-   VCEColorFormat p_SurfaceFormat/* = VCESurfaceFormat_NV12*/
185
-) {
186
-   AMF_RESULT res;
187
-
188
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Initializing...");
189
-
190
-   // Solve the optimized away issue.
191
-   m_EncoderType = p_Type;
192
-   m_SurfaceFormat = p_SurfaceFormat;
193
-   m_UseOpenCL = p_OpenCL;
194
-   m_Flag_IsStarted = false;
195
-   m_Flag_FirstFrameReceived = false;
196
-   m_Flag_FirstFrameSubmitted = false;
197
-   m_FrameSize.first = 64; m_FrameSize.second = 64;
198
-   m_FrameRate.first = 30; m_FrameRate.second = 1;
199
-   m_FrameRateDivisor = ((double_t)m_FrameRate.first / (double_t)m_FrameRate.second);
200
-   m_FrameRateReverseDivisor = ((double_t)m_FrameRate.second / (double_t)m_FrameRate.first);
201
-   m_InputQueueLimit = (uint32_t)(m_FrameRateDivisor * 3);
202
-   m_InputQueueLastSize = 0;
203
-   m_TimerPeriod = 1;
204
-
205
-   // AMF
206
-   m_AMF = AMF::GetInstance();
207
-   m_AMFFactory = m_AMF->GetFactory();
208
-   /// AMF Context
209
-   res = m_AMFFactory->CreateContext(&m_AMFContext);
210
-   if (res != AMF_OK) {
211
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Creating a context object failed with error %ls (code %ld).", res);
212
-   }
213
-
214
-   // API Init
215
-   if (p_DeviceId == "") { // Use primary/available AMD devices only.
216
-       p_DeviceId = Plugin::AMD::VCECapabilities::GetInstance()->GetDevices().begin()->UniqueId;
217
-   }
218
-   m_APIDevice = Plugin::API::APIBase::CreateBestAvailableAPI(Plugin::API::APIBase::GetDeviceForUniqueId(p_DeviceId));
219
-   switch (m_APIDevice->GetType()) {
220
-       case Plugin::API::APIType_Direct3D11:
221
-           res = m_AMFContext->InitDX11(m_APIDevice->GetContext());
222
-           m_MemoryType = VCEMemoryType_DirectX11;
223
-           break;
224
-       case Plugin::API::APIType_Direct3D9:
225
-           res = m_AMFContext->InitDX9(m_APIDevice->GetContext());
226
-           m_MemoryType = VCEMemoryType_DirectX9;
227
-           break;
228
-       case Plugin::API::APIType_OpenGL:
229
-           res = m_AMFContext->InitOpenGL(m_APIDevice->GetContext(), nullptr, nullptr);
230
-           m_MemoryType = VCEMemoryType_OpenGL;
231
-           break;
232
-       case Plugin::API::APIType_Base: // Not the best case, but whatever.
233
-           m_UseOpenCL = false;
234
-           m_MemoryType = VCEMemoryType_Host;
235
-           break;
236
-   }
237
-   if (res != AMF_OK)
238
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Initializing 3D queue failed with error %ls (code %ld).", res);
239
-
240
-   if (m_UseOpenCL) {
241
-       res = m_AMFContext->InitOpenCL(nullptr);
242
-       if (res != AMF_OK)
243
-           ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> InitOpenCL failed with error %ls (code %ld).", res);
244
-       m_AMFContext->GetCompute(amf::AMF_MEMORY_OPENCL, &m_AMFCompute);
245
-   }
246
-
247
-   /// AMF Component (Encoder)
248
-   switch (p_Type) {
249
-       case VCEEncoderType_AVC:
250
-           res = m_AMFFactory->CreateComponent(m_AMFContext, AMFVideoEncoderVCE_AVC, &m_AMFEncoder);
251
-           break;
252
-       case VCEEncoderType_SVC:
253
-           res = m_AMFFactory->CreateComponent(m_AMFContext, AMFVideoEncoderVCE_SVC, &m_AMFEncoder);
254
-           break;
255
-       case VCEEncoderType_HEVC:
256
-           res = m_AMFFactory->CreateComponent(m_AMFContext, L"AMFVideoEncoderHW_HEVC", &m_AMFEncoder);
257
-           break;
258
-   }
259
-   if (res != AMF_OK)
260
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Creating a component object failed with error %ls (code %ld).", res);
261
-
262
-   /// AMF Component (Converter)
263
-   res = m_AMFFactory->CreateComponent(m_AMFContext, AMFVideoConverter, &m_AMFConverter);
264
-   if (res != AMF_OK)
265
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Unable to create VideoConverter component, error %ls (code %ld).", res);
266
-   m_AMFConverter->SetProperty(AMF_VIDEO_CONVERTER_MEMORY_TYPE, Utility::MemoryTypeAsAMF(m_MemoryType));
267
-   m_AMFConverter->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_FORMAT, Utility::SurfaceFormatAsAMF(m_SurfaceFormat));
268
-
269
-   printDebugInfo(m_AMFEncoder);
270
-
271
-   AMF_LOG_DEBUG("Initialization complete!");
272
-}
273
-
274
-Plugin::AMD::VCEEncoder::~VCEEncoder() {
275
-   if (m_Flag_IsStarted)
276
-       Stop();
277
-
278
-   // AMF
279
-   if (m_AMFConverter) {
280
-       m_AMFConverter->Terminate();
281
-       m_AMFConverter = nullptr;
282
-   }
283
-   if (m_AMFEncoder) {
284
-       m_AMFEncoder->Terminate();
285
-       m_AMFEncoder = nullptr;
286
-   }
287
-   if (m_AMFContext) {
288
-       m_AMFContext->Terminate();
289
-       m_AMFContext = nullptr;
290
-   }
291
-   m_AMFFactory = nullptr;
292
-}
293
-
294
-void Plugin::AMD::VCEEncoder::Start() {
295
-   // Set proper Timer resolution.
296
-   m_TimerPeriod = 1;
297
-   while (timeBeginPeriod(m_TimerPeriod) == TIMERR_NOCANDO) {
298
-       ++m_TimerPeriod;
299
-   }
300
-
301
-   // Create Encoder
302
-   AMF_RESULT res = m_AMFEncoder->Init(Utility::SurfaceFormatAsAMF(m_SurfaceFormat),
303
-       m_FrameSize.first, m_FrameSize.second);
304
-   if (res != AMF_OK)
305
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Encoder initialization failed with error %ls (code %ld).", res);
306
-
307
-   // Create Converter
308
-   m_AMFConverter->SetProperty(AMF_VIDEO_CONVERTER_COLOR_PROFILE, AMF_VIDEO_CONVERTER_COLOR_PROFILE_709);
309
-   //m_AMFConverter->SetProperty(L"NominalRange", this->IsFullColorRangeEnabled());
310
-   res = m_AMFConverter->Init(Utility::SurfaceFormatAsAMF(m_SurfaceFormat), m_FrameSize.first, m_FrameSize.second);
311
-   if (res != AMF_OK)
312
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Converter initialization failed with error %ls (code %ld).", res);
313
-
314
-   m_Flag_IsStarted = true;
315
-
316
-   // Threading
317
-   m_Input.thread = std::thread(&(Plugin::AMD::VCEEncoder::InputThreadMain), this);
318
-   m_Output.thread = std::thread(&(Plugin::AMD::VCEEncoder::OutputThreadMain), this);
319
-}
320
-
321
-void Plugin::AMD::VCEEncoder::Restart() {
322
-   if (!m_Flag_IsStarted)
323
-       return;
324
-
325
-   std::unique_lock<std::mutex> ilock(m_Input.mutex);
326
-   std::unique_lock<std::mutex> olock(m_Output.mutex);
327
-
328
-   // Create Encoder
329
-   AMF_RESULT res = m_AMFEncoder->ReInit(m_FrameSize.first, m_FrameSize.second);
330
-   if (res != AMF_OK)
331
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Initialization failed with error %ls (code %ld).", res);
332
-}
333
-
334
-void Plugin::AMD::VCEEncoder::Stop() {
335
-   // Restore Timer precision.
336
-   if (m_TimerPeriod != 0) {
337
-       timeEndPeriod(m_TimerPeriod);
338
-   }
339
-
340
-   m_Flag_IsStarted = false;
341
-
342
-   // Threading
343
-   m_Output.condvar.notify_all();
344
-   #if defined _WIN32 || defined _WIN64
345
-   { // Windows: Force terminate Thread after 1 second of waiting.
346
-       std::thread::native_handle_type hnd = m_Output.thread.native_handle();
347
-
348
-       uint32_t res = WaitForSingleObject((HANDLE)hnd, 1000);
349
-       switch (res) {
350
-           case WAIT_OBJECT_0:
351
-               m_Output.thread.join();
352
-               break;
353
-           default:
354
-               m_Output.thread.detach();
355
-               TerminateThread((HANDLE)hnd, 0);
356
-               break;
357
-       }
358
-   }
359
-   #else
360
-   m_Output.thread.join();
361
-   #endif
362
-
363
-   m_Input.condvar.notify_all();
364
-   #if defined _WIN32 || defined _WIN64
365
-   { // Windows: Force terminate Thread after 1 second of waiting.
366
-       std::thread::native_handle_type hnd = m_Input.thread.native_handle();
367
-
368
-       uint32_t res = WaitForSingleObject((HANDLE)hnd, 1000);
369
-       switch (res) {
370
-           case WAIT_OBJECT_0:
371
-               m_Input.thread.join();
372
-               break;
373
-           default:
374
-               m_Input.thread.detach();
375
-               TerminateThread((HANDLE)hnd, 0);
376
-               break;
377
-       }
378
-   }
379
-   #else
380
-   m_Input.thread.join();
381
-   #endif
382
-
383
-   // Stop AMF Encoder
384
-   if (m_AMFEncoder) {
385
-       m_AMFEncoder->Drain();
386
-       m_AMFEncoder->Flush();
387
-   }
388
-
389
-   // Clear Queues, Data
390
-   std::queue<amf::AMFSurfacePtr>().swap(m_Input.queue);
391
-   std::queue<amf::AMFDataPtr>().swap(m_Output.queue);
392
-   m_PacketDataBuffer.clear();
393
-   m_ExtraDataBuffer.clear();
394
-}
395
-
396
-bool Plugin::AMD::VCEEncoder::IsStarted() {
397
-   return m_Flag_IsStarted;
398
-}
399
-
400
-bool Plugin::AMD::VCEEncoder::SendInput(struct encoder_frame* frame) {
401
-   // Early-Exception if not encoding.
402
-   if (!m_Flag_IsStarted) {
403
-       const char* error = "<" __FUNCTION_NAME__ "> Attempted to send input while not running.";
404
-       AMF_LOG_ERROR("%s", error);
405
-       throw std::exception(error);
406
-   }
407
-
408
-   // Convert Frame into a Surface and queue it.
409
-   if (frame != nullptr) {
410
-       amf::AMFSurfacePtr pAMFSurface = CreateSurfaceFromFrame(frame);
411
-       if (pAMFSurface) {
412
-           // Set Surface Properties
413
-           pAMFSurface->SetPts(frame->pts / m_FrameRate.second);
414
-           pAMFSurface->SetProperty(L"Frame", frame->pts);
415
-           pAMFSurface->SetDuration((uint64_t)ceil(m_FrameRateReverseDivisor * AMF_SECOND));
416
-
417
-           // Add to Queue
418
-           std::unique_lock<std::mutex> qlock(m_Input.queuemutex);
419
-           size_t uiQueueSize = m_Input.queue.size();
420
-
421
-           if (uiQueueSize >= m_InputQueueLimit) {
422
-               AMF_LOG_WARNING("Submission queue is full, dropping frame instead...");
423
-           } else {
424
-               m_Input.queue.push(pAMFSurface);
425
-               if (m_InputQueueLastSize != uiQueueSize) {
426
-                   int32_t delta = ((int32_t)uiQueueSize - (int32_t)m_InputQueueLastSize);
427
-                   if (uiQueueSize == 0) {
428
-                       AMF_LOG_DEBUG("Submission queue is empty. (%d/%d/%d)", uiQueueSize, delta, m_InputQueueLimit);
429
-                       m_InputQueueLastSize = uiQueueSize;
430
-                   } else if (delta >= 5) {
431
-                       AMF_LOG_WARNING("Submission queue size is growing. (%d/%d/%d)", uiQueueSize, delta, m_InputQueueLimit);
432
-                       m_InputQueueLastSize = uiQueueSize;
433
-                   } else if (delta <= -5) {
434
-                       AMF_LOG_INFO("Submission queue size is shrinking. (%d/%d/%d)", uiQueueSize, delta, m_InputQueueLimit);
435
-                       m_InputQueueLastSize = uiQueueSize;
436
-                   }
437
-               }
438
-           }
439
-       } else {
440
-           AMF_LOG_ERROR("Unable copy frame for submission, terminating...");
441
-           return false;
442
-       }
443
-   }
444
-
445
-   /// Signal Thread Wakeup
446
-   m_Input.condvar.notify_all();
447
-
448
-   // WORKAROUND: Block for at most 5 seconds until the first frame has been submitted.
449
-   if (!m_Flag_FirstFrameSubmitted) {
450
-       auto startsubmit = std::chrono::high_resolution_clock::now();
451
-       auto diff = std::chrono::high_resolution_clock::now() - startsubmit;
452
-       do {
453
-           diff = std::chrono::high_resolution_clock::now() - startsubmit;
454
-           std::this_thread::sleep_for(std::chrono::milliseconds(m_TimerPeriod));
455
-       } while ((diff <= std::chrono::seconds(5)) && !m_Flag_FirstFrameSubmitted);
456
-       if (!m_Flag_FirstFrameSubmitted)
457
-           throw std::exception("Unable to submit first frame, terminating...");
458
-       else
459
-           AMF_LOG_INFO("First submission took %d nanoseconds.", diff.count());
460
-   }
461
-
462
-   return true;
463
-}
464
-
465
-bool Plugin::AMD::VCEEncoder::GetOutput(struct encoder_packet* packet, bool* received_packet) {
466
-   // Early-Exception if not encoding.
467
-   if (!m_Flag_IsStarted) {
468
-       const char* error = "<" __FUNCTION_NAME__ "> Attempted to send input while not running.";
469
-       AMF_LOG_ERROR("%s", error);
470
-       throw std::exception(error);
471
-   }
472
-
473
-   /// Signal Thread Wakeup
474
-   m_Output.condvar.notify_all();
475
-
476
-   if (received_packet != nullptr) {
477
-       amf::AMFDataPtr pAMFData;
478
-       { // Attempt to dequeue an Item.
479
-           std::unique_lock<std::mutex> qlock(m_Output.queuemutex);
480
-           if (m_Output.queue.size() == 0)
481
-               return true;
482
-
483
-           pAMFData = m_Output.queue.front();
484
-           m_Output.queue.pop();
485
-       }
486
-
487
-       // We've got a DataPtr, let's use it.
488
-       amf::AMFBufferPtr pAMFBuffer = amf::AMFBufferPtr(pAMFData);
489
-
490
-       // Assemble Packet
491
-       packet->type = OBS_ENCODER_VIDEO;
492
-       /// Data
493
-       size_t oldBufferSize = pAMFBuffer->GetSize();
494
-       if (m_PacketDataBuffer.size() < oldBufferSize) {
495
-           size_t newBufferSize = (size_t)exp2(ceil(log2(oldBufferSize)));
496
-           AMF_LOG_DEBUG("Packet Buffer was resized to %d byte from %d byte.", newBufferSize, m_PacketDataBuffer.size());
497
-           m_PacketDataBuffer.resize(newBufferSize);
498
-       }
499
-       packet->data = m_PacketDataBuffer.data();
500
-       packet->size = oldBufferSize;
501
-       std::memcpy(packet->data, pAMFBuffer->GetNative(), packet->size);
502
-       /// Timestamps
503
-       packet->dts = (pAMFData->GetPts() - 2) * m_FrameRate.second; // Offset by 2 to support B-Pictures
504
-       pAMFBuffer->GetProperty(L"Frame", &packet->pts);
505
-       { /// Packet Priority & Keyframe
506
-           uint64_t pktType;
507
-           pAMFData->GetProperty(AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE, &pktType);
508
-
509
-           switch ((AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_ENUM)pktType) {
510
-               case AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR://
511
-                   packet->keyframe = true;                // IDR-Frames are Key-Frames that contain a lot of information.
512
-                   packet->priority = 3;                   // Highest priority, always continue streaming with these.
513
-                   //packet->drop_priority = 3;                // Dropped IDR-Frames can only be replaced by the next IDR-Frame.
514
-                   break;
515
-               case AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_I:  // I-Frames need only a previous I- or IDR-Frame.
516
-                   packet->priority = 2;                   // I- and IDR-Frames will most likely be present.
517
-               //  packet->drop_priority = 2;              // So we can continue with a I-Frame when streaming.
518
-               //  break;
519
-               case AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_P:  // P-Frames need either a previous P-, I- or IDR-Frame.
520
-                   packet->priority = 1;                   // We can safely assume that at least one of these is present.
521
-               //  packet->drop_priority = 1;              // So we can continue with a P-Frame when streaming.
522
-               //  break;
523
-               case AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_B:  // B-Frames need either a parent B-, P-, I- or IDR-Frame.
524
-                   packet->priority = 0;                   // We don't know if the last non-dropped frame was a B-Frame.
525
-               //  packet->drop_priority = 1;              // So require a P-Frame or better to continue streaming.
526
-               //  break;
527
-           }
528
-       }
529
-       *received_packet = true;
530
-
531
-       // Debug: Packet Information
532
-       std::vector<wchar_t> fileName(128);
533
-       mbstowcs(fileName.data(), __FILE__, fileName.size());
534
-       std::vector<wchar_t> functionName(128);
535
-       mbstowcs(functionName.data(), __FUNCTION__, functionName.size());
536
-       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);
537
-   }
538
-
539
-   return true;
540
-}
541
-
542
-bool Plugin::AMD::VCEEncoder::GetExtraData(uint8_t**& extra_data, size_t*& extra_data_size) {
543
-   if (!m_AMFContext || !m_AMFEncoder)
544
-       throw std::exception("<" __FUNCTION_NAME__ "> Called while not initialized.");
545
-
546
-   if (!m_Flag_IsStarted)
547
-       throw std::exception("<" __FUNCTION_NAME__ "> Called while not encoding.");
548
-
549
-   amf::AMFVariant var;
550
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_EXTRADATA, &var);
551
-   if (res == AMF_OK && var.type == amf::AMF_VARIANT_INTERFACE) {
552
-       amf::AMFBufferPtr buf(var.pInterface);
553
-
554
-       *extra_data_size = buf->GetSize();
555
-       m_ExtraDataBuffer.resize(*extra_data_size);
556
-       std::memcpy(m_ExtraDataBuffer.data(), buf->GetNative(), *extra_data_size);
557
-       *extra_data = m_ExtraDataBuffer.data();
558
-
559
-       return true;
560
-   }
561
-   return false;
562
-}
563
-
564
-void Plugin::AMD::VCEEncoder::GetVideoInfo(struct video_scale_info*& vsi) {
565
-   if (!m_AMFContext || !m_AMFEncoder)
566
-       throw std::exception("<" __FUNCTION_NAME__ "> Called while not initialized.");
567
-
568
-   if (!m_Flag_IsStarted)
569
-       throw std::exception("<" __FUNCTION_NAME__ "> Called while not encoding.");
570
-
571
-   switch (m_SurfaceFormat) {
572
-       // 4:2:0 Formats
573
-       case VCEColorFormat_NV12:
574
-           vsi->format = VIDEO_FORMAT_NV12;
575
-           break;
576
-       case VCEColorFormat_I420:
577
-           vsi->format = VIDEO_FORMAT_I420;
578
-           break;
579
-       // 4:2:2 Formats
580
-       case VCEColorFormat_YUY2:
581
-           vsi->format = VIDEO_FORMAT_YUY2;
582
-           break;
583
-       // Uncompressed
584
-       case VCEColorFormat_RGBA:
585
-           vsi->format = VIDEO_FORMAT_RGBA;
586
-           break;
587
-       case VCEColorFormat_BGRA:
588
-           vsi->format = VIDEO_FORMAT_BGRA;
589
-           break;
590
-       // Other
591
-       case VCEColorFormat_GRAY:
592
-           vsi->format = VIDEO_FORMAT_Y800;
593
-           break;
594
-   }
595
-
596
-   // AMF requires Partial Range for some reason.
597
-   if (this->IsFullColorRangeEnabled()) { // Only use Full range if actually enabled.
598
-       vsi->range = VIDEO_RANGE_FULL;
599
-   } else {
600
-       vsi->range = VIDEO_RANGE_PARTIAL;
601
-   }
602
-   // Also Colorspace is automatic, see: https://github.com/GPUOpen-LibrariesAndSDKs/AMF/issues/6#issuecomment-243473568
603
-   //if (this->GetFrameSize().second <= 780) { // SD content is .601, HD content is .709
604
-   //  vsi->colorspace = VIDEO_CS_601;
605
-   //} else {
606
-   //  vsi->colorspace = VIDEO_CS_709;
607
-   //}
608
-}
609
-
610
-void Plugin::AMD::VCEEncoder::InputThreadLogic() { // Thread Loop that handles Surface Submission
611
-   // Assign Thread Name
612
-   static const char* __threadName = "enc-amf Input Thread";
613
-   SetThreadName(__threadName);
614
-
615
-   // Core Loop
616
-   std::unique_lock<std::mutex> lock(m_Input.mutex);
617
-   uint32_t repeatSurfaceSubmission = 0;
618
-   do {
619
-       m_Input.condvar.wait(lock);
620
-
621
-       // Assign Thread Name
622
-       static const char* __threadName = "enc-amf Input Thread";
623
-       SetThreadName(__threadName);
624
-
625
-       // Skip to check if isStarted is false.
626
-       if (!m_Flag_IsStarted)
627
-           continue;
628
-
629
-       // Dequeue Surface
630
-       amf::AMFSurfacePtr surface;
631
-       {
632
-           std::unique_lock<std::mutex> qlock(m_Input.queuemutex);
633
-           if (m_Input.queue.size() == 0)
634
-               continue; // Queue is empty, 
635
-           surface = m_Input.queue.front();
636
-       }
637
-
638
-       /// Convert Frame
639
-       AMF_RESULT res;
640
-       amf::AMFDataPtr outbuf;
641
-
642
-       res = m_AMFConverter->SubmitInput(surface);
643
-       if (res != AMF_OK)
644
-           ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Unable to submit Frame to Converter, error %ls (code %ld).", res);
645
-       res = m_AMFConverter->QueryOutput(&outbuf);
646
-       if (res != AMF_OK)
647
-           ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Unable to retrieve Frame from Converter, error %ls (code %ld).", res);
648
-
649
-       /// Submit to AMF
650
-       res = m_AMFEncoder->SubmitInput(outbuf);
651
-       if (res == AMF_OK) {
652
-           m_Flag_FirstFrameSubmitted = true;
653
-
654
-           { // Remove Surface from Queue
655
-               std::unique_lock<std::mutex> qlock(m_Input.queuemutex);
656
-               m_Input.queue.pop();
657
-           }
658
-
659
-           // Reset AMF_INPUT_FULL retries.
660
-           repeatSurfaceSubmission = 0;
661
-
662
-           // Continue with next Surface.
663
-           m_Input.condvar.notify_all();
664
-       } else if (res == AMF_INPUT_FULL) {
665
-           m_Output.condvar.notify_all();
666
-           if (repeatSurfaceSubmission < 5) {
667
-               repeatSurfaceSubmission++;
668
-
669
-               std::this_thread::sleep_for(std::chrono::milliseconds(1));
670
-               m_Input.condvar.notify_all();
671
-           }
672
-       } else if (res == AMF_EOF) {
673
-           // This should never happen, but on the off-chance that it does, just straight up leave the loop.
674
-           break;
675
-       } else {
676
-           // Unknown, unexpected return code.
677
-           std::vector<char> msgBuf(128);
678
-           FormatTextWithAMFError(&msgBuf, "%ls (code %d)", Plugin::AMD::AMF::GetInstance()->GetTrace()->GetResultText(res), res);
679
-           AMF_LOG_WARNING("<" __FUNCTION_NAME__ "> SubmitInput failed with error %s.", msgBuf.data());
680
-       }
681
-   } while (m_Flag_IsStarted);
682
-}
683
-
684
-void Plugin::AMD::VCEEncoder::OutputThreadLogic() {    // Thread Loop that handles Querying
685
-   // Assign Thread Name
686
-   static const char* __threadName = "enc-amf Output Thread";
687
-   SetThreadName(__threadName);
688
-
689
-   // Core Loop
690
-   std::unique_lock<std::mutex> lock(m_Output.mutex);
691
-   do {
692
-       m_Output.condvar.wait(lock);
693
-
694
-       // Assign Thread Name
695
-       static const char* __threadName = "enc-amf Output Thread";
696
-       SetThreadName(__threadName);
697
-
698
-       // Skip to check if isStarted is false.
699
-       if (!m_Flag_IsStarted)
700
-           continue;
701
-
702
-       amf::AMFDataPtr pData = amf::AMFDataPtr();
703
-       AMF_RESULT res = m_AMFEncoder->QueryOutput(&pData);
704
-       if (res == AMF_OK) {
705
-           m_Flag_FirstFrameReceived = true;
706
-
707
-           { // Queue
708
-               std::unique_lock<std::mutex> qlock(m_Output.queuemutex);
709
-               m_Output.queue.push(pData);
710
-           }
711
-
712
-           // Continue querying until nothing is left.
713
-           m_Output.condvar.notify_all();
714
-       } else if (res == AMF_REPEAT) {
715
-           m_Input.condvar.notify_all();
716
-       } else if (res == AMF_EOF) {
717
-           // This should never happen, but on the off-chance that it does, just straight up leave the loop.
718
-           break;
719
-       } else {
720
-           // Unknown, unexpected return code.
721
-           std::vector<char> msgBuf(128);
722
-           FormatTextWithAMFError(&msgBuf, "%s (code %d)", res);
723
-           AMF_LOG_WARNING("<" __FUNCTION_NAME__ "> QueryOutput failed with error %s.", msgBuf.data());
724
-       }
725
-   } while (m_Flag_IsStarted);
726
-}
727
-
728
-amf::AMFSurfacePtr Plugin::AMD::VCEEncoder::CreateSurfaceFromFrame(struct encoder_frame*& frame) {
729
-   AMF_RESULT res = AMF_UNEXPECTED;
730
-   amf::AMFSurfacePtr pSurface = nullptr;
731
-   if (m_UseOpenCL) {
732
-       amf_size l_origin[] = { 0, 0, 0 };
733
-       amf_size l_size0[] = { m_FrameSize.first, m_FrameSize.second, 1 };
734
-       amf_size l_size1[] = { m_FrameSize.first >> 1, m_FrameSize.second >> 1, 1 };
735
-
736
-       res = m_AMFContext->AllocSurface(Utility::MemoryTypeAsAMF(m_MemoryType),
737
-           Utility::SurfaceFormatAsAMF(m_SurfaceFormat),
738
-           m_FrameSize.first, m_FrameSize.second, &pSurface);
739
-       if (res != AMF_OK) // Unable to create Surface
740
-           ThrowExceptionWithAMFError("AllocSurface failed with error %ls (code %d).", res);
741
-
742
-       amf::AMFComputeSyncPointPtr pSyncPoint;
743
-       m_AMFCompute->PutSyncPoint(&pSyncPoint);
744
-       pSurface->Convert(amf::AMF_MEMORY_OPENCL);
745
-       m_AMFCompute->CopyPlaneFromHost(frame->data[0], l_origin, l_size0, frame->linesize[0], pSurface->GetPlaneAt(0), false);
746
-       m_AMFCompute->CopyPlaneFromHost(frame->data[1], l_origin, l_size1, frame->linesize[1], pSurface->GetPlaneAt(1), false);
747
-       m_AMFCompute->FinishQueue();
748
-       pSurface->Convert(Utility::MemoryTypeAsAMF(m_MemoryType));
749
-       pSyncPoint->Wait();
750
-   } else {
751
-       res = m_AMFContext->AllocSurface(amf::AMF_MEMORY_HOST, Utility::SurfaceFormatAsAMF(m_SurfaceFormat),
752
-           m_FrameSize.first, m_FrameSize.second, &pSurface);
753
-       if (res != AMF_OK) // Unable to create Surface
754
-           ThrowExceptionWithAMFError("AllocSurface failed with error %ls (code %d).", res);
755
-
756
-       size_t planeCount = pSurface->GetPlanesCount();
757
-       for (uint8_t i = 0; i < planeCount; i++) {
758
-           amf::AMFPlanePtr plane = pSurface->GetPlaneAt(i);
759
-           void* plane_nat = plane->GetNative();
760
-           int32_t height = plane->GetHeight();
761
-           int32_t hpitch = plane->GetHPitch();
762
-
763
-           for (int32_t py = 0; py < height; py++) {
764
-               int32_t plane_off = py * hpitch;
765
-               int32_t frame_off = py * frame->linesize[i];
766
-               std::memcpy(static_cast<void*>(static_cast<uint8_t*>(plane_nat) + plane_off), static_cast<void*>(frame->data[i] + frame_off), frame->linesize[i]);
767
-           }
768
-       }
769
-
770
-       // Convert to AMF native type.
771
-       pSurface->Convert(Utility::MemoryTypeAsAMF(m_MemoryType));
772
-   }
773
-
774
-   return pSurface;
775
-}
776
-
777
-//////////////////////////////////////////////////////////////////////////
778
-// AMF Properties
779
-//////////////////////////////////////////////////////////////////////////
780
-
781
-void Plugin::AMD::VCEEncoder::LogProperties() {
782
-   AMF_LOG_INFO("-- AMD Advanced Media Framework VCE Encoder --");
783
-   AMF_LOG_INFO("Initialization Parameters: ");
784
-   AMF_LOG_INFO("  Memory Type: %s", Utility::MemoryTypeAsString(m_MemoryType));
785
-   if (m_MemoryType != VCEMemoryType_Host) {
786
-       AMF_LOG_INFO("  Device: %s", m_APIDevice->GetDevice().Name.c_str());
787
-       AMF_LOG_INFO("  OpenCL: %s", m_UseOpenCL ? "Enabled" : "Disabled");
788
-   }
789
-   AMF_LOG_INFO("  Surface Format: %s", Utility::SurfaceFormatAsString(m_SurfaceFormat));
790
-   try { AMF_LOG_INFO("  Color Profile: %s", this->GetColorProfile() == VCEColorProfile_709 ? "709" : "601"); } catch (...) {}
791
-   try { AMF_LOG_INFO("  Color Range: %s", this->IsFullColorRangeEnabled() ? "Full" : "Partial"); } catch (...) {}
792
-   AMF_LOG_INFO("Static Parameters: ");
793
-   AMF_LOG_INFO("  Usage: %s", Utility::UsageAsString(this->GetUsage()));
794
-   AMF_LOG_INFO("  Profile: %s %d.%d", Utility::ProfileAsString(this->GetProfile()), this->GetProfileLevel() / 10, this->GetProfileLevel() % 10);
795
-   AMF_LOG_INFO("  Maximum Long-Term Reference Frames: %d", this->GetMaximumLongTermReferenceFrames());
796
-   AMF_LOG_INFO("  Frame Size: %dx%d", this->GetFrameSize().first, this->GetFrameSize().second);
797
-   AMF_LOG_INFO("  Frame Rate: %d/%d", this->GetFrameRate().first, this->GetFrameRate().second);
798
-   AMF_LOG_INFO("  Quality Preset: %s", Utility::QualityPresetAsString(this->GetQualityPreset()));
799
-   AMF_LOG_INFO("  Scan Type: %s", this->GetScanType() == VCEScanType_Progressive ? "Progressive" : "Interlaced");
800
-   try { AMF_LOG_INFO("  Coding Type: %s", Utility::CodingTypeAsString(this->GetCodingType())); } catch (...) {}
801
-   AMF_LOG_INFO("Rate Control Parameters: ");
802
-   AMF_LOG_INFO("  Method: %s", Utility::RateControlMethodAsString(this->GetRateControlMethod()));
803
-   AMF_LOG_INFO("  Bitrate: ");
804
-   AMF_LOG_INFO("    Target: %d bits", this->GetTargetBitrate());
805
-   AMF_LOG_INFO("    Peak: %d bits", this->GetPeakBitrate());
806
-   AMF_LOG_INFO("  Quantization Parameter: ");
807
-   AMF_LOG_INFO("    Minimum: %d", this->GetMinimumQP());
808
-   AMF_LOG_INFO("    Maximum: %d", this->GetMaximumQP());
809
-   AMF_LOG_INFO("    I-Frame: %d", this->GetIFrameQP());
810
-   AMF_LOG_INFO("    P-Frame: %d", this->GetPFrameQP());
811
-   if (VCECapabilities::GetInstance()->GetDeviceCaps(m_APIDevice->GetDevice(), VCEEncoderType_AVC).supportsBFrames) {
812
-       try { AMF_LOG_INFO("    B-Frame: %d", this->GetBFrameQP()); } catch (...) {}
813
-       try { AMF_LOG_INFO("    B-Picture Delta QP: %d", this->GetBPictureDeltaQP()); } catch (...) {}
814
-       try { AMF_LOG_INFO("    Reference B-Picture Delta QP: %d", this->GetReferenceBPictureDeltaQP()); } catch (...) {}
815
-   } else {
816
-       AMF_LOG_INFO("    B-Frame: N/A");
817
-       AMF_LOG_INFO("    B-Picture Delta QP: N/A");
818
-       AMF_LOG_INFO("    Reference B-Picture Delta QP: N/A");
819
-   }
820
-   AMF_LOG_INFO("  VBV Buffer: ");
821
-   AMF_LOG_INFO("    Size: %d bits", this->GetVBVBufferSize());
822
-   AMF_LOG_INFO("    Initial Fullness: %f%%", this->GetInitialVBVBufferFullness() * 100.0);
823
-   AMF_LOG_INFO("  Flags: ");
824
-   AMF_LOG_INFO("    Filler Data: %s", this->IsFillerDataEnabled() ? "Enabled" : "Disabled");
825
-   AMF_LOG_INFO("    Frame Skipping: %s", this->IsFrameSkippingEnabled() ? "Enabled" : "Disabled");
826
-   AMF_LOG_INFO("    Enforce HRD Restrictions: %s", this->IsEnforceHRDRestrictionsEnabled() ? "Enabled" : "Disabled");
827
-   AMF_LOG_INFO("  Maximum Access Unit Size: %d bits", this->GetMaximumAccessUnitSize());
828
-   AMF_LOG_INFO("Picture Control Parameters: ");
829
-   AMF_LOG_INFO("  IDR Period: %d frames", this->GetIDRPeriod());
830
-   AMF_LOG_INFO("  Header Insertion Spacing: %d frames", this->GetHeaderInsertionSpacing());
831
-   AMF_LOG_INFO("  Deblocking Filter: %s", this->IsDeblockingFilterEnabled() ? "Enabled" : "Disabled");
832
-   if (VCECapabilities::GetInstance()->GetDeviceCaps(m_APIDevice->GetDevice(), VCEEncoderType_AVC).supportsBFrames) {
833
-       AMF_LOG_INFO("  B-Picture Pattern: %d", this->GetBPicturePattern());
834
-       AMF_LOG_INFO("  B-Picture Reference: %s", this->IsBPictureReferenceEnabled() ? "Enabled" : "Disabled");
835
-   } else {
836
-       AMF_LOG_INFO("  B-Picture Pattern: N/A");
837
-       AMF_LOG_INFO("  B-Picture Reference: N/A");
838
-   }
839
-   AMF_LOG_INFO("  Intra-Refresh MBs Number per Slot: %d", this->GetIntraRefreshMBsNumberPerSlot());
840
-   AMF_LOG_INFO("  Slices Per Frame: %d", this->GetSlicesPerFrame());
841
-   AMF_LOG_INFO("Motion Estimation Parameters: ");
842
-   AMF_LOG_INFO("  Half Pixel: %s", this->IsHalfPixelMotionEstimationEnabled() ? "Enabled" : "Disabled");
843
-   AMF_LOG_INFO("  Quarter Pixel: %s", this->IsQuarterPixelMotionEstimationEnabled() ? "Enabled" : "Disabled");
844
-   AMF_LOG_INFO("Experimental Parameters: ");
845
-   try { AMF_LOG_INFO("  Wait For Task: %s", this->IsWaitForTaskEnabled() ? "Enabled" : "Disabled"); } catch (...) {}
846
-   try { AMF_LOG_INFO("  Aspect Ratio: %d:%d", this->GetAspectRatio().first, this->GetAspectRatio().second); } catch (...) {}
847
-   try { AMF_LOG_INFO("  MaxNumRefFrames: %d", this->GetMaximumNumberOfReferenceFrames()); } catch (...) {}
848
-   try { AMF_LOG_INFO("  MaxMBPerSec: %d", this->GetMaxMBPerSec()); } catch (...) {}
849
-   try { AMF_LOG_INFO("  Pre-Analysis Pass: %s", this->IsRateControlPreanalysisEnabled() ? "Enabled" : "Disabled"); } catch (...) {}
850
-   //try { AMF_LOG_INFO("  Quality Enhancement Mode: %s", Utility::QualityEnhancementModeAsString(this->GetQualityEnhancementMode())); } catch (...) {}
851
-   try { AMF_LOG_INFO("  VBAQ: %s", this->IsVBAQEnabled() ? "Enabled" : "Disabled"); } catch (...) {}
852
-
853
-   Plugin::AMD::VCECapabilities::ReportDeviceCapabilities(m_APIDevice->GetDevice());
854
-
855
-   printDebugInfo(m_AMFEncoder);
856
-   AMF_LOG_INFO("-- AMD Advanced Media Framework VCE Encoder --");
857
-}
858
-
859
-/************************************************************************/
860
-/* Static Properties                                                    */
861
-/************************************************************************/
862
-
863
-void Plugin::AMD::VCEEncoder::SetUsage(VCEUsage usage) {
864
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_USAGE,
865
-       (uint32_t)Utility::UsageAsAMF(usage));
866
-   if (res != AMF_OK) {
867
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).",
868
-           res, Utility::UsageAsString(usage));
869
-   }
870
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", Utility::UsageAsString(usage));
871
-}
872
-
873
-Plugin::AMD::VCEUsage Plugin::AMD::VCEEncoder::GetUsage() {
874
-   uint32_t usage;
875
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_USAGE, &usage);
876
-   if (res != AMF_OK) {
877
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
878
-   }
879
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.",
880
-       Utility::UsageAsString(Utility::UsageFromAMF(usage)));
881
-   return Utility::UsageFromAMF(usage);
882
-}
883
-
884
-void Plugin::AMD::VCEEncoder::SetQualityPreset(VCEQualityPreset preset) {
885
-   static AMF_VIDEO_ENCODER_QUALITY_PRESET_ENUM CustomToAMF[] = {
886
-       AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED,
887
-       AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED,
888
-       AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY,
889
-   };
890
-   static char* CustomToName[] = {
891
-       "Speed",
892
-       "Balanced",
893
-       "Quality",
894
-   };
895
-
896
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_QUALITY_PRESET, (uint32_t)CustomToAMF[preset]);
897
-   if (res != AMF_OK) {
898
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, CustomToName[preset]);
899
-   }
900
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", CustomToName[preset]);
901
-}
902
-
903
-Plugin::AMD::VCEQualityPreset Plugin::AMD::VCEEncoder::GetQualityPreset() {
904
-   static VCEQualityPreset AMFToCustom[] = {
905
-       VCEQualityPreset_Balanced,
906
-       VCEQualityPreset_Speed,
907
-       VCEQualityPreset_Quality,
908
-   };
909
-   static char* CustomToName[] = {
910
-       "Speed",
911
-       "Balanced",
912
-       "Quality",
913
-   };
914
-
915
-   uint32_t preset;
916
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_QUALITY_PRESET, &preset);
917
-   if (res != AMF_OK) {
918
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
919
-   }
920
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", CustomToName[AMFToCustom[preset]]);
921
-   return AMFToCustom[preset];
922
-}
923
-
924
-void Plugin::AMD::VCEEncoder::SetProfile(VCEProfile profile) {
925
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_PROFILE, (uint32_t)profile);
926
-   if (res != AMF_OK) {
927
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, Utility::ProfileAsString(profile));
928
-   }
929
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", Utility::ProfileAsString(profile));
930
-}
931
-
932
-Plugin::AMD::VCEProfile Plugin::AMD::VCEEncoder::GetProfile() {
933
-   uint32_t profile;
934
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_PROFILE, &profile);
935
-   if (res != AMF_OK) {
936
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
937
-   }
938
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", Utility::ProfileAsString((VCEProfile)profile));
939
-   return (VCEProfile)profile;
940
-}
941
-
942
-void Plugin::AMD::VCEEncoder::SetProfileLevel(VCEProfileLevel level) {
943
-   // Automatic Detection
944
-   if (level == VCEProfileLevel_Automatic) {
945
-       auto frameSize = this->GetFrameSize();
946
-       auto frameRate = this->GetFrameRate();
947
-       level = Plugin::Utility::GetMinimumProfileLevel(frameSize, frameRate);
948
-   }
949
-
950
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_PROFILE_LEVEL, (uint32_t)level);
951
-   if (res != AMF_OK) {
952
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, level);
953
-   }
954
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", level);
955
-}
956
-
957
-Plugin::AMD::VCEProfileLevel Plugin::AMD::VCEEncoder::GetProfileLevel() {
958
-   uint32_t profileLevel;
959
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_PROFILE_LEVEL, &profileLevel);
960
-   if (res != AMF_OK) {
961
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
962
-   }
963
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", profileLevel);
964
-   return (VCEProfileLevel)(profileLevel);
965
-}
966
-
967
-void Plugin::AMD::VCEEncoder::SetMaximumLongTermReferenceFrames(uint32_t maximumLTRFrames) {
968
-   // Clamp Parameter Value
969
-   maximumLTRFrames = max(min(maximumLTRFrames, 2), 0);
970
-
971
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_MAX_LTR_FRAMES, (uint32_t)maximumLTRFrames);
972
-   if (res != AMF_OK) {
973
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, maximumLTRFrames);
974
-   }
975
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", maximumLTRFrames);
976
-}
977
-
978
-uint32_t Plugin::AMD::VCEEncoder::GetMaximumLongTermReferenceFrames() {
979
-   uint32_t maximumLTRFrames;
980
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MAX_LTR_FRAMES, &maximumLTRFrames);
981
-   if (res != AMF_OK) {
982
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
983
-   }
984
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", maximumLTRFrames);
985
-   return maximumLTRFrames;
986
-}
987
-
988
-void Plugin::AMD::VCEEncoder::SetCodingType(VCECodingType type) {
989
-   AMF_RESULT res = m_AMFEncoder->SetProperty(L"CABACEnable", type);
990
-   if (res != AMF_OK) {
991
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, Utility::CodingTypeAsString(type));
992
-   }
993
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", Utility::CodingTypeAsString(type));
994
-}
995
-
996
-VCECodingType Plugin::AMD::VCEEncoder::GetCodingType() {
997
-   uint64_t type;
998
-   AMF_RESULT res = m_AMFEncoder->GetProperty(L"CABACEnable", &type);
999
-   if (res != AMF_OK) {
1000
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1001
-   }
1002
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", Utility::CodingTypeAsString((VCECodingType)type));
1003
-   return (VCECodingType)type;
1004
-}
1005
-
1006
-/************************************************************************/
1007
-/* Frame Properties                                                     */
1008
-/************************************************************************/
1009
-
1010
-void Plugin::AMD::VCEEncoder::SetColorProfile(VCEColorProfile profile) {
1011
-   AMF_VIDEO_CONVERTER_COLOR_PROFILE_ENUM pluginToAMF[] = {
1012
-       AMF_VIDEO_CONVERTER_COLOR_PROFILE_601,
1013
-       AMF_VIDEO_CONVERTER_COLOR_PROFILE_709,
1014
-       AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020,
1015
-   };
1016
-   const char* pluginToString[] = {
1017
-       "601",
1018
-       "709",
1019
-       "2020",
1020
-   };
1021
-
1022
-   AMF_RESULT res = m_AMFConverter->SetProperty(AMF_VIDEO_CONVERTER_COLOR_PROFILE,
1023
-       pluginToAMF[profile]);
1024
-   if (res != AMF_OK)
1025
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Unable to set Color Profile, error %ls (code %ld).", res);
1026
-   m_ColorProfile = profile;
1027
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", pluginToString[profile]);
1028
-}
1029
-
1030
-Plugin::AMD::VCEColorProfile Plugin::AMD::VCEEncoder::GetColorProfile() {
1031
-   return m_ColorProfile;
1032
-}
1033
-
1034
-void Plugin::AMD::VCEEncoder::SetFullColorRangeEnabled(bool enabled) {
1035
-   // Info from Mikhail:
1036
-   // - Name may change in the future
1037
-   // - Use GetProperty or GetPropertyDescription to test for older or newer drivers.
1038
-   const wchar_t* names[] = {
1039
-       L"NominalRange", // 16.11.2 and below.
1040
-       L"FullRange"
1041
-   };
1042
-
1043
-   bool enabledTest;
1044
-   AMF_RESULT res = AMF_INVALID_ARG;
1045
-   for (size_t i = 0; i < 2; i++) {
1046
-       if (m_AMFEncoder->GetProperty(names[i], &enabledTest) == AMF_OK) {
1047
-           m_AMFConverter->SetProperty(names[i], enabled);
1048
-           res = m_AMFEncoder->SetProperty(names[i], enabled);
1049
-           break;
1050
-       }
1051
-   }
1052
-   if (res != AMF_OK)
1053
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1054
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1055
-}
1056
-
1057
-bool Plugin::AMD::VCEEncoder::IsFullColorRangeEnabled() {
1058
-   // Info from Mikhail:
1059
-   // - Name may change in the future
1060
-   // - Use GetProperty or GetPropertyDescription to test for older or newer drivers.
1061
-   const wchar_t* names[] = {
1062
-       L"NominalRange", // 16.11.2 and below.
1063
-       L"FullRange"
1064
-   };
1065
-
1066
-   bool enabled;
1067
-   AMF_RESULT res = AMF_INVALID_ARG;
1068
-   for (size_t i = 0; i < 2; i++) {
1069
-       res = m_AMFEncoder->GetProperty(names[i], &enabled);
1070
-       if (res == AMF_OK) {
1071
-           break;
1072
-       }
1073
-   }
1074
-   if (res != AMF_OK)
1075
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1076
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1077
-   return enabled;
1078
-}
1079
-
1080
-void Plugin::AMD::VCEEncoder::SetScanType(VCEScanType scanType) {
1081
-   static AMF_VIDEO_ENCODER_SCANTYPE_ENUM CustomToAMF[] = {
1082
-       AMF_VIDEO_ENCODER_SCANTYPE_PROGRESSIVE,
1083
-       AMF_VIDEO_ENCODER_SCANTYPE_INTERLACED,
1084
-   };
1085
-   static char* CustomToName[] = {
1086
-       "Progressive",
1087
-       "Interlaced",
1088
-   };
1089
-
1090
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_SCANTYPE, (uint32_t)CustomToAMF[scanType]);
1091
-   if (res != AMF_OK) {
1092
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, CustomToName[scanType]);
1093
-   }
1094
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", CustomToName[scanType]);
1095
-}
1096
-
1097
-Plugin::AMD::VCEScanType Plugin::AMD::VCEEncoder::GetScanType() {
1098
-   static char* CustomToName[] = {
1099
-       "Progressive",
1100
-       "Interlaced",
1101
-   };
1102
-
1103
-   uint32_t scanType;
1104
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_SCANTYPE, &scanType);
1105
-   if (res != AMF_OK) {
1106
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1107
-   }
1108
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", CustomToName[scanType]);
1109
-   return (Plugin::AMD::VCEScanType)scanType;
1110
-}
1111
-
1112
-void Plugin::AMD::VCEEncoder::SetFrameSize(uint32_t width, uint32_t height) {
1113
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_FRAMESIZE, ::AMFConstructSize(width, height));
1114
-   if (res != AMF_OK) {
1115
-       std::vector<char> msgBuf(128);
1116
-       sprintf(msgBuf.data(), "%dx%d", width, height);
1117
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, msgBuf.data());
1118
-   }
1119
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %dx%d.", width, height);
1120
-   m_FrameSize.first = width;
1121
-   m_FrameSize.second = height;
1122
-
1123
-   if (this->GetProfileLevel() == VCEProfileLevel_Automatic)
1124
-       this->SetProfileLevel(VCEProfileLevel_Automatic);
1125
-}
1126
-
1127
-std::pair<uint32_t, uint32_t> Plugin::AMD::VCEEncoder::GetFrameSize() {
1128
-   AMFSize frameSize;
1129
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_FRAMESIZE, &frameSize);
1130
-   if (res != AMF_OK) {
1131
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1132
-   }
1133
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %dx%d.", frameSize.width, frameSize.height);
1134
-   m_FrameSize.first = frameSize.width;
1135
-   m_FrameSize.second = frameSize.height;
1136
-
1137
-   if (this->GetProfileLevel() == VCEProfileLevel_Automatic)
1138
-       this->SetProfileLevel(VCEProfileLevel_Automatic);
1139
-
1140
-   return std::pair<uint32_t, uint32_t>(m_FrameSize);
1141
-}
1142
-
1143
-void Plugin::AMD::VCEEncoder::SetFrameRate(uint32_t num, uint32_t den) {
1144
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_FRAMERATE, ::AMFConstructRate(num, den));
1145
-   if (res != AMF_OK) {
1146
-       std::vector<char> msgBuf;
1147
-       sprintf(msgBuf.data(), "%d/%d", num, den);
1148
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, msgBuf.data());
1149
-   }
1150
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d/%d.", num, den);
1151
-   m_FrameRate.first = num;
1152
-   m_FrameRate.second = den;
1153
-   m_FrameRateDivisor = (double_t)m_FrameRate.first / (double_t)m_FrameRate.second;
1154
-   m_FrameRateReverseDivisor = ((double_t)m_FrameRate.second / (double_t)m_FrameRate.first);
1155
-   m_InputQueueLimit = (uint32_t)ceil(m_FrameRateDivisor * 3);
1156
-
1157
-   if (this->GetProfileLevel() == VCEProfileLevel_Automatic)
1158
-       this->SetProfileLevel(VCEProfileLevel_Automatic);
1159
-}
1160
-
1161
-std::pair<uint32_t, uint32_t> Plugin::AMD::VCEEncoder::GetFrameRate() {
1162
-   AMFRate frameRate;
1163
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_FRAMERATE, &frameRate);
1164
-   if (res != AMF_OK) {
1165
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1166
-   }
1167
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d/%d.", frameRate.num, frameRate.den);
1168
-   m_FrameRate.first = frameRate.num;
1169
-   m_FrameRate.second = frameRate.den;
1170
-   m_FrameRateDivisor = (double_t)frameRate.num / (double_t)frameRate.den;
1171
-   m_InputQueueLimit = (uint32_t)ceil(m_FrameRateDivisor * 3);
1172
-
1173
-   if (this->GetProfileLevel() == VCEProfileLevel_Automatic)
1174
-       this->SetProfileLevel(VCEProfileLevel_Automatic);
1175
-
1176
-   return std::pair<uint32_t, uint32_t>(m_FrameRate);
1177
-}
1178
-
1179
-/************************************************************************/
1180
-/* Rate Control Properties                                              */
1181
-/************************************************************************/
1182
-
1183
-void Plugin::AMD::VCEEncoder::SetRateControlMethod(VCERateControlMethod method) {
1184
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD,
1185
-       (uint64_t)Utility::RateControlMethodAsAMF(method));
1186
-   if (res != AMF_OK) {
1187
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).",
1188
-           res, Utility::RateControlMethodAsString(method));
1189
-   }
1190
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.",
1191
-       Utility::RateControlMethodAsString(method));
1192
-}
1193
-
1194
-Plugin::AMD::VCERateControlMethod Plugin::AMD::VCEEncoder::GetRateControlMethod() {
1195
-   uint32_t method;
1196
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD, &method);
1197
-   if (res != AMF_OK) {
1198
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1199
-   }
1200
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.",
1201
-       Utility::RateControlMethodAsString(Utility::RateControlMethodFromAMF(method)));
1202
-   return Utility::RateControlMethodFromAMF(method);
1203
-}
1204
-
1205
-void Plugin::AMD::VCEEncoder::SetTargetBitrate(uint32_t bitrate) {
1206
-   // Clamp Value
1207
-   bitrate = clamp(bitrate, 10000,
1208
-       Plugin::AMD::VCECapabilities::GetInstance()->GetDeviceCaps(m_APIDevice->GetDevice(), VCEEncoderType_AVC).maxBitrate);
1209
-
1210
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_TARGET_BITRATE, bitrate);
1211
-   if (res != AMF_OK) {
1212
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d bits failed with error %ls (code %d).", res, bitrate);
1213
-   }
1214
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d bits.", bitrate);
1215
-}
1216
-
1217
-uint32_t Plugin::AMD::VCEEncoder::GetTargetBitrate() {
1218
-   uint32_t bitrate;
1219
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_TARGET_BITRATE, &bitrate);
1220
-   if (res != AMF_OK) {
1221
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1222
-   }
1223
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d bits.", bitrate);
1224
-   return bitrate;
1225
-}
1226
-
1227
-void Plugin::AMD::VCEEncoder::SetPeakBitrate(uint32_t bitrate) {
1228
-   // Clamp Value
1229
-   bitrate = clamp(bitrate, 10000,
1230
-       Plugin::AMD::VCECapabilities::GetInstance()->GetDeviceCaps(m_APIDevice->GetDevice(), VCEEncoderType_AVC).maxBitrate);
1231
-
1232
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_PEAK_BITRATE, (uint32_t)bitrate);
1233
-   if (res != AMF_OK) {
1234
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d bits failed with error %ls (code %d).", res, bitrate);
1235
-   }
1236
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d bits.", bitrate);
1237
-}
1238
-
1239
-uint32_t Plugin::AMD::VCEEncoder::GetPeakBitrate() {
1240
-   uint32_t bitrate;
1241
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_PEAK_BITRATE, &bitrate);
1242
-   if (res != AMF_OK) {
1243
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1244
-   }
1245
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d bits.", bitrate);
1246
-   return bitrate;
1247
-}
1248
-
1249
-void Plugin::AMD::VCEEncoder::SetMinimumQP(uint8_t qp) {
1250
-   // Clamp Value
1251
-   qp = clamp(qp, 0, 51);
1252
-
1253
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_MIN_QP, (uint32_t)qp);
1254
-   if (res != AMF_OK) {
1255
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, qp);
1256
-   }
1257
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
1258
-}
1259
-
1260
-uint8_t Plugin::AMD::VCEEncoder::GetMinimumQP() {
1261
-   uint32_t qp;
1262
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MIN_QP, &qp);
1263
-   if (res != AMF_OK) {
1264
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1265
-   }
1266
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", qp);
1267
-   return (uint8_t)qp;
1268
-}
1269
-
1270
-void Plugin::AMD::VCEEncoder::SetMaximumQP(uint8_t qp) {
1271
-   // Clamp Value
1272
-   qp = clamp(qp, 0, 51);
1273
-
1274
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_MAX_QP, (uint32_t)qp);
1275
-   if (res != AMF_OK) {
1276
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, qp);
1277
-   }
1278
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
1279
-}
1280
-
1281
-uint8_t Plugin::AMD::VCEEncoder::GetMaximumQP() {
1282
-   uint32_t qp;
1283
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MAX_QP, &qp);
1284
-   if (res != AMF_OK) {
1285
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1286
-   }
1287
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", qp);
1288
-   return (uint8_t)qp;
1289
-}
1290
-
1291
-void Plugin::AMD::VCEEncoder::SetIFrameQP(uint8_t qp) {
1292
-   // Clamp Value
1293
-   qp = clamp(qp, 0, 51);
1294
-
1295
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_QP_I, (uint32_t)qp);
1296
-   if (res != AMF_OK) {
1297
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, qp);
1298
-   }
1299
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
1300
-}
1301
-
1302
-uint8_t Plugin::AMD::VCEEncoder::GetIFrameQP() {
1303
-   uint32_t qp;
1304
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_QP_I, &qp);
1305
-   if (res != AMF_OK) {
1306
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1307
-   }
1308
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", qp);
1309
-   return (uint8_t)qp;
1310
-}
1311
-
1312
-void Plugin::AMD::VCEEncoder::SetPFrameQP(uint8_t qp) {
1313
-   // Clamp Value
1314
-   qp = clamp(qp, 0, 51);
1315
-
1316
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_QP_P, (uint32_t)qp);
1317
-   if (res != AMF_OK) {
1318
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, qp);
1319
-   }
1320
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
1321
-}
1322
-
1323
-uint8_t Plugin::AMD::VCEEncoder::GetPFrameQP() {
1324
-   uint32_t qp;
1325
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_QP_P, &qp);
1326
-   if (res != AMF_OK) {
1327
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1328
-   }
1329
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", qp);
1330
-   return (uint8_t)qp;
1331
-}
1332
-
1333
-void Plugin::AMD::VCEEncoder::SetBFrameQP(uint8_t qp) {
1334
-   // Clamp Value
1335
-   qp = clamp(qp, 0, 51);
1336
-
1337
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_QP_B, (uint32_t)qp);
1338
-   if (res != AMF_OK) {
1339
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, qp);
1340
-   }
1341
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
1342
-}
1343
-
1344
-uint8_t Plugin::AMD::VCEEncoder::GetBFrameQP() {
1345
-   uint32_t qp;
1346
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_QP_B, &qp);
1347
-   if (res != AMF_OK) {
1348
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1349
-   }
1350
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", qp);
1351
-   return (uint8_t)qp;
1352
-}
1353
-
1354
-void Plugin::AMD::VCEEncoder::SetBPictureDeltaQP(int8_t qp) {
1355
-   // Clamp Value
1356
-   qp = clamp(qp, -10, 10);
1357
-
1358
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_B_PIC_DELTA_QP, (int32_t)qp);
1359
-   if (res != AMF_OK) {
1360
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, qp);
1361
-   }
1362
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
1363
-}
1364
-
1365
-int8_t Plugin::AMD::VCEEncoder::GetBPictureDeltaQP() {
1366
-   int32_t qp;
1367
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_B_PIC_DELTA_QP, &qp);
1368
-   if (res != AMF_OK) {
1369
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1370
-   }
1371
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", qp);
1372
-   return (int8_t)qp;
1373
-}
1374
-
1375
-void Plugin::AMD::VCEEncoder::SetReferenceBPictureDeltaQP(int8_t qp) {
1376
-   // Clamp Value
1377
-   qp = clamp(qp, -10, 10);
1378
-
1379
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_REF_B_PIC_DELTA_QP, (int32_t)qp);
1380
-   if (res != AMF_OK) {
1381
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, qp);
1382
-   }
1383
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
1384
-}
1385
-
1386
-int8_t Plugin::AMD::VCEEncoder::GetReferenceBPictureDeltaQP() {
1387
-   int32_t qp;
1388
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_REF_B_PIC_DELTA_QP, &qp);
1389
-   if (res != AMF_OK) {
1390
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1391
-   }
1392
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", qp);
1393
-   return (int8_t)qp;
1394
-}
1395
-
1396
-void Plugin::AMD::VCEEncoder::SetVBVBufferSize(uint32_t size) {
1397
-   // Clamp Value
1398
-   size = clamp(size, 1000, 100000000); // 1kbit to 100mbit.
1399
-
1400
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_VBV_BUFFER_SIZE, (uint32_t)size);
1401
-   if (res != AMF_OK) {
1402
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d bits failed with error %ls (code %d).", res, size);
1403
-   }
1404
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d bits.", size);
1405
-}
1406
-
1407
-void Plugin::AMD::VCEEncoder::SetVBVBufferAutomatic(double_t strictness) {
1408
-   uint32_t strictBitrate = 1000, looseBitrate = 100000000;
1409
-
1410
-   // Strict VBV Buffer Size = Bitrate / FPS
1411
-   // Loose VBV Buffer Size = Bitrate
1412
-
1413
-   switch (this->GetRateControlMethod()) {
1414
-       case VCERateControlMethod_ConstantBitrate:
1415
-       case VCERateControlMethod_VariableBitrate_LatencyConstrained:
1416
-           looseBitrate = this->GetTargetBitrate();
1417
-           break;
1418
-       case VCERateControlMethod_VariableBitrate_PeakConstrained:
1419
-           looseBitrate = max(this->GetTargetBitrate(), this->GetPeakBitrate());
1420
-           break;
1421
-       case VCERateControlMethod_ConstantQP:
1422
-           // When using Constant QP, one will have to pick a QP that is decent
1423
-           //  in both quality and bitrate. We can easily calculate both the QP
1424
-           //  required for an average bitrate and the average bitrate itself 
1425
-           //  with these formulas:
1426
-           // BITRATE = ((1 - (QP / 51)) ^ 2) * ((Width * Height) * 1.5 * (FPSNumerator / FPSDenumerator))
1427
-           // QP = (1 - sqrt(BITRATE / ((Width * Height) * 1.5 * (FPSNumerator / FPSDenumerator)))) * 51
1428
-
1429
-           auto frameSize = this->GetFrameSize();
1430
-           auto frameRate = this->GetFrameRate();
1431
-
1432
-           double_t bitrate = frameSize.first * frameSize.second;
1433
-           switch (this->m_SurfaceFormat) {
1434
-               case VCEColorFormat_NV12:
1435
-               case VCEColorFormat_I420:
1436
-                   bitrate *= 1.5;
1437
-                   break;
1438
-               case VCEColorFormat_YUY2:
1439
-                   bitrate *= 4;
1440
-                   break;
1441
-               case VCEColorFormat_BGRA:
1442
-               case VCEColorFormat_RGBA:
1443
-                   bitrate *= 3;
1444
-                   break;
1445
-               case VCEColorFormat_GRAY:
1446
-                   bitrate *= 1;
1447
-                   break;
1448
-           }
1449
-           bitrate *= frameRate.first / frameRate.second;
1450
-
1451
-           uint8_t qp_i, qp_p, qp_b;
1452
-           qp_i = this->GetIFrameQP();
1453
-           qp_p = this->GetPFrameQP();
1454
-           try { qp_b = this->GetBFrameQP(); } catch (...) { qp_b = 51; }
1455
-           double_t qp = 1 - ((double_t)(min(min(qp_i, qp_p), qp_b)) / 51.0);
1456
-           qp = max(qp * qp, 0.001); // Needs to be at least 0.001.
1457
-
1458
-           looseBitrate = static_cast<uint32_t>(bitrate * qp);
1459
-           break;
1460
-   }
1461
-   strictBitrate = static_cast<uint32_t>(looseBitrate * m_FrameRateReverseDivisor);
1462
-
1463
-   #define PI 3.14159265
1464
-   double_t interpVal = (sin(max(min(strictness, 1.0), 0.0) * 90 * (PI / 180))); // sin curve?
1465
-   uint32_t realBitrate = static_cast<uint32_t>(ceil((strictBitrate * interpVal) + (looseBitrate * (1.0 - interpVal))));
1466
-   this->SetVBVBufferSize(realBitrate);
1467
-}
1468
-
1469
-uint32_t Plugin::AMD::VCEEncoder::GetVBVBufferSize() {
1470
-   uint32_t size;
1471
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_VBV_BUFFER_SIZE, &size);
1472
-   if (res != AMF_OK) {
1473
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1474
-   }
1475
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", size);
1476
-   return size;
1477
-}
1478
-
1479
-void Plugin::AMD::VCEEncoder::SetInitialVBVBufferFullness(double_t fullness) {
1480
-   // Clamp Value
1481
-   fullness = max(min(fullness, 1), 0); // 0 to 100 %
1482
-
1483
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_INITIAL_VBV_BUFFER_FULLNESS, (uint32_t)(fullness * 64));
1484
-   if (res != AMF_OK) {
1485
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %f%% failed with error %ls (code %d).", res, fullness * 100);
1486
-   }
1487
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %f%%.", fullness * 100);
1488
-}
1489
-
1490
-double_t Plugin::AMD::VCEEncoder::GetInitialVBVBufferFullness() {
1491
-   uint32_t vbvBufferFullness;
1492
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_INITIAL_VBV_BUFFER_FULLNESS, &vbvBufferFullness);
1493
-   if (res != AMF_OK) {
1494
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1495
-   }
1496
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %f%%.", vbvBufferFullness / 64.0 * 100.0);
1497
-   return ((double_t)vbvBufferFullness / 64.0);
1498
-}
1499
-
1500
-void Plugin::AMD::VCEEncoder::SetMaximumAccessUnitSize(uint32_t size) {
1501
-   // Clamp Value
1502
-   size = max(min(size, 100000000), 0); // 1kbit to 100mbit.
1503
-
1504
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_MAX_AU_SIZE, (uint32_t)size);
1505
-   if (res != AMF_OK) {
1506
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d bits failed with error %ls (code %d).", res, size);
1507
-   }
1508
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d bits.", size);
1509
-}
1510
-
1511
-uint32_t Plugin::AMD::VCEEncoder::GetMaximumAccessUnitSize() {
1512
-   uint32_t size;
1513
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MAX_AU_SIZE, &size);
1514
-   if (res != AMF_OK) {
1515
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1516
-   }
1517
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", size);
1518
-   return size;
1519
-}
1520
-
1521
-void Plugin::AMD::VCEEncoder::SetFillerDataEnabled(bool enabled) {
1522
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_FILLER_DATA_ENABLE, enabled);
1523
-   if (res != AMF_OK) {
1524
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1525
-   }
1526
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1527
-}
1528
-
1529
-bool Plugin::AMD::VCEEncoder::IsFillerDataEnabled() {
1530
-   bool enabled;
1531
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_FILLER_DATA_ENABLE, &enabled);
1532
-   if (res != AMF_OK) {
1533
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1534
-   }
1535
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1536
-   return enabled;
1537
-}
1538
-
1539
-void Plugin::AMD::VCEEncoder::SetFrameSkippingEnabled(bool enabled) {
1540
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_RATE_CONTROL_SKIP_FRAME_ENABLE, enabled);
1541
-   if (res != AMF_OK) {
1542
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1543
-   }
1544
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1545
-}
1546
-
1547
-bool Plugin::AMD::VCEEncoder::IsFrameSkippingEnabled() {
1548
-   bool enabled;
1549
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_RATE_CONTROL_SKIP_FRAME_ENABLE, &enabled);
1550
-   if (res != AMF_OK) {
1551
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1552
-   }
1553
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1554
-   return enabled;
1555
-}
1556
-
1557
-void Plugin::AMD::VCEEncoder::SetEnforceHRDRestrictionsEnabled(bool enabled) {
1558
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_ENFORCE_HRD, enabled);
1559
-   if (res != AMF_OK) {
1560
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1561
-   }
1562
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1563
-}
1564
-
1565
-bool Plugin::AMD::VCEEncoder::IsEnforceHRDRestrictionsEnabled() {
1566
-   bool enabled;
1567
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_ENFORCE_HRD, &enabled);
1568
-   if (res != AMF_OK) {
1569
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1570
-   }
1571
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1572
-   return enabled;
1573
-}
1574
-
1575
-/************************************************************************/
1576
-/* Picture Control Properties                                           */
1577
-/************************************************************************/
1578
-
1579
-void Plugin::AMD::VCEEncoder::SetIDRPeriod(uint32_t period) {
1580
-   // Clamp Value
1581
-   period = max(min(period, m_FrameRate.second * 1000), 1); // 1-1000 so that OBS can actually quit.
1582
-
1583
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_IDR_PERIOD, (uint32_t)period);
1584
-   if (res != AMF_OK) {
1585
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, period);
1586
-   }
1587
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", period);
1588
-}
1589
-
1590
-uint32_t Plugin::AMD::VCEEncoder::GetIDRPeriod() {
1591
-   int32_t period;
1592
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_IDR_PERIOD, &period);
1593
-   if (res != AMF_OK) {
1594
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1595
-   }
1596
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", period);
1597
-   return period;
1598
-}
1599
-
1600
-void Plugin::AMD::VCEEncoder::SetHeaderInsertionSpacing(uint32_t spacing) {
1601
-   // Clamp Value
1602
-   spacing = max(min(spacing, m_FrameRate.second * 1000), 0);
1603
-
1604
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_HEADER_INSERTION_SPACING, (uint32_t)spacing);
1605
-   if (res != AMF_OK) {
1606
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, spacing);
1607
-   }
1608
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", spacing);
1609
-}
1610
-
1611
-uint32_t Plugin::AMD::VCEEncoder::GetHeaderInsertionSpacing() {
1612
-   int32_t headerInsertionSpacing;
1613
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_HEADER_INSERTION_SPACING, &headerInsertionSpacing);
1614
-   if (res != AMF_OK) {
1615
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1616
-   }
1617
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", headerInsertionSpacing);
1618
-   return headerInsertionSpacing;
1619
-}
1620
-
1621
-void Plugin::AMD::VCEEncoder::SetBPicturePattern(VCEBPicturePattern pattern) {
1622
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_B_PIC_PATTERN, (uint32_t)pattern);
1623
-   if (res != AMF_OK) {
1624
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, pattern);
1625
-   }
1626
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", pattern);
1627
-}
1628
-
1629
-Plugin::AMD::VCEBPicturePattern Plugin::AMD::VCEEncoder::GetBPicturePattern() {
1630
-   uint32_t pattern;
1631
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_B_PIC_PATTERN, &pattern);
1632
-   if (res != AMF_OK) {
1633
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1634
-   }
1635
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", pattern);
1636
-   return (Plugin::AMD::VCEBPicturePattern)pattern;
1637
-}
1638
-
1639
-void Plugin::AMD::VCEEncoder::SetBPictureReferenceEnabled(bool enabled) {
1640
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_B_REFERENCE_ENABLE, enabled);
1641
-   if (res != AMF_OK) {
1642
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1643
-   }
1644
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1645
-}
1646
-
1647
-bool Plugin::AMD::VCEEncoder::IsBPictureReferenceEnabled() {
1648
-   bool enabled;
1649
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_B_REFERENCE_ENABLE, &enabled);
1650
-   if (res != AMF_OK) {
1651
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1652
-   }
1653
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1654
-   return enabled;
1655
-}
1656
-
1657
-void Plugin::AMD::VCEEncoder::SetDeblockingFilterEnabled(bool enabled) {
1658
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_DE_BLOCKING_FILTER, enabled);
1659
-   if (res != AMF_OK) {
1660
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1661
-   }
1662
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1663
-}
1664
-
1665
-bool Plugin::AMD::VCEEncoder::IsDeblockingFilterEnabled() {
1666
-   bool enabled;
1667
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_DE_BLOCKING_FILTER, &enabled);
1668
-   if (res != AMF_OK) {
1669
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1670
-   }
1671
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1672
-   return enabled;
1673
-}
1674
-
1675
-void Plugin::AMD::VCEEncoder::SetSlicesPerFrame(uint32_t slices) {
1676
-   slices = max(slices, 1);
1677
-
1678
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_SLICES_PER_FRAME, (uint32_t)slices);
1679
-   if (res != AMF_OK) {
1680
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, slices);
1681
-   }
1682
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", slices);
1683
-}
1684
-
1685
-uint32_t Plugin::AMD::VCEEncoder::GetSlicesPerFrame() {
1686
-   uint32_t slices;
1687
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_SLICES_PER_FRAME, &slices);
1688
-   if (res != AMF_OK) {
1689
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1690
-   }
1691
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", slices);
1692
-   return slices;
1693
-}
1694
-
1695
-void Plugin::AMD::VCEEncoder::SetIntraRefreshMBsNumberPerSlot(uint32_t mbs) {
1696
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_INTRA_REFRESH_NUM_MBS_PER_SLOT, (uint32_t)mbs);
1697
-   if (res != AMF_OK) {
1698
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, mbs);
1699
-   }
1700
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", mbs);
1701
-}
1702
-
1703
-uint32_t Plugin::AMD::VCEEncoder::GetIntraRefreshMBsNumberPerSlot() {
1704
-   int32_t mbs;
1705
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_INTRA_REFRESH_NUM_MBS_PER_SLOT, &mbs);
1706
-   if (res != AMF_OK) {
1707
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1708
-   }
1709
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", mbs);
1710
-   return mbs;
1711
-}
1712
-
1713
-/************************************************************************/
1714
-/* Miscellaneous Control Properties                                     */
1715
-/************************************************************************/
1716
-
1717
-void Plugin::AMD::VCEEncoder::SetHalfPixelMotionEstimationEnabled(bool enabled) {
1718
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_MOTION_HALF_PIXEL, enabled);
1719
-   if (res != AMF_OK) {
1720
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1721
-   }
1722
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1723
-}
1724
-
1725
-bool Plugin::AMD::VCEEncoder::IsHalfPixelMotionEstimationEnabled() {
1726
-   bool enabled;
1727
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MOTION_HALF_PIXEL, &enabled);
1728
-   if (res != AMF_OK) {
1729
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1730
-   }
1731
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1732
-   return enabled;
1733
-}
1734
-
1735
-void Plugin::AMD::VCEEncoder::SetQuarterPixelMotionEstimationEnabled(bool enabled) {
1736
-   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_MOTION_QUARTERPIXEL, enabled);
1737
-   if (res != AMF_OK) {
1738
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1739
-   }
1740
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1741
-}
1742
-
1743
-bool Plugin::AMD::VCEEncoder::IsQuarterPixelMotionEstimationEnabled() {
1744
-   bool enabled;
1745
-   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MOTION_QUARTERPIXEL, &enabled);
1746
-   if (res != AMF_OK) {
1747
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1748
-   }
1749
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1750
-   return enabled;
1751
-}
1752
-
1753
-/************************************************************************/
1754
-/* Hidden Properties                                                    */
1755
-/************************************************************************/
1756
-
1757
-void Plugin::AMD::VCEEncoder::SetGOPSize(uint32_t size) {
1758
-   AMF_LOG_WARNING("Using unsupported SetGOPSize function. Unexpected behaviour may happen.");
1759
-
1760
-   AMF_RESULT res = m_AMFEncoder->SetProperty(L"GOPSize", (uint32_t)size);
1761
-   if (res != AMF_OK) {
1762
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, size);
1763
-   }
1764
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", size);
1765
-}
1766
-
1767
-uint32_t Plugin::AMD::VCEEncoder::GetGOPSize() {
1768
-   AMF_LOG_WARNING("Using unsupported GetGOPSize function. Unexpected behaviour may happen.");
1769
-
1770
-   uint32_t size;
1771
-   AMF_RESULT res = m_AMFEncoder->GetProperty(L"GOPSize", &size);
1772
-   if (res != AMF_OK) {
1773
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1774
-   }
1775
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", size);
1776
-   return size;
1777
-}
1778
-
1779
-void Plugin::AMD::VCEEncoder::SetWaitForTaskEnabled(bool enabled) {
1780
-   AMF_RESULT res = m_AMFEncoder->SetProperty(L"WaitForTask", enabled);
1781
-   if (res != AMF_OK) {
1782
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1783
-   }
1784
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1785
-}
1786
-
1787
-bool Plugin::AMD::VCEEncoder::IsWaitForTaskEnabled() {
1788
-   bool enabled;
1789
-   AMF_RESULT res = m_AMFEncoder->GetProperty(L"WaitForTask", &enabled);
1790
-   if (res != AMF_OK) {
1791
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1792
-   }
1793
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1794
-   return enabled;
1795
-}
1796
-
1797
-void Plugin::AMD::VCEEncoder::SetAspectRatio(uint32_t num, uint32_t den) {
1798
-   AMF_RESULT res = m_AMFEncoder->SetProperty(L"AspectRatio", ::AMFConstructRate(num, den));
1799
-   if (res != AMF_OK) {
1800
-       std::vector<char> msgBuf;
1801
-       sprintf(msgBuf.data(), "%d:%d", num, den);
1802
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, msgBuf.data());
1803
-   }
1804
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d:%d.", num, den);
1805
-}
1806
-
1807
-std::pair<uint32_t, uint32_t> Plugin::AMD::VCEEncoder::GetAspectRatio() {
1808
-   AMFRate aspectRatio;
1809
-   AMF_RESULT res = m_AMFEncoder->GetProperty(L"AspectRatio", &aspectRatio);
1810
-   if (res != AMF_OK) {
1811
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1812
-   }
1813
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d:%d.", aspectRatio.num, aspectRatio.den);
1814
-   return std::pair<uint32_t, uint32_t>(aspectRatio.num, aspectRatio.den);
1815
-}
1816
-
1817
-void Plugin::AMD::VCEEncoder::SetMaximumNumberOfReferenceFrames(uint32_t numFrames) {
1818
-   AMF_RESULT res = m_AMFEncoder->SetProperty(L"MaxNumRefFrames", (uint32_t)numFrames);
1819
-   if (res != AMF_OK) {
1820
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, numFrames);
1821
-   }
1822
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", numFrames);
1823
-}
1824
-
1825
-uint32_t Plugin::AMD::VCEEncoder::GetMaximumNumberOfReferenceFrames() {
1826
-   uint32_t numFrames;
1827
-   AMF_RESULT res = m_AMFEncoder->GetProperty(L"MaxNumRefFrames", &numFrames);
1828
-   if (res != AMF_OK) {
1829
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1830
-   }
1831
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", numFrames);
1832
-   return numFrames;
1833
-}
1834
-
1835
-uint32_t Plugin::AMD::VCEEncoder::GetMaxMBPerSec() {
1836
-   uint32_t maxMBPerSec;
1837
-   AMF_RESULT res = m_AMFEncoder->GetProperty(L"MaxMBPerSec", &maxMBPerSec);
1838
-   if (res != AMF_OK) {
1839
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1840
-   }
1841
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", maxMBPerSec);
1842
-   return maxMBPerSec;
1843
-}
1844
-
1845
-void Plugin::AMD::VCEEncoder::SetVBAQEnabled(bool enabled) {
1846
-
1847
-}
1848
-
1849
-bool Plugin::AMD::VCEEncoder::IsVBAQEnabled() {
1850
-   return false;
1851
-}
1852
-
1853
-void Plugin::AMD::VCEEncoder::SetRateControlPreanalysisEnabled(bool enabled) {
1854
-   AMF_RESULT res = m_AMFEncoder->SetProperty(L"RateControlPreanalysisEnable", enabled);
1855
-   if (res != AMF_OK) {
1856
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1857
-   }
1858
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1859
-}
1860
-
1861
-bool Plugin::AMD::VCEEncoder::IsRateControlPreanalysisEnabled() {
1862
-   bool enabled;
1863
-   AMF_RESULT res = m_AMFEncoder->GetProperty(L"RateControlPreanalysisEnable", &enabled);
1864
-   if (res != AMF_OK) {
1865
-       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1866
-   }
1867
-   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1868
-   return enabled;
1869
-}
1870
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Source/amd-amf.cpp Deleted
266
 
1
@@ -1,264 +0,0 @@
2
-/*
3
-MIT License
4
-
5
-Copyright (c) 2016 Michael Fabian Dirks
6
-
7
-Permission is hereby granted, free of charge, to any person obtaining a copy
8
-of this software and associated documentation files (the "Software"), to deal
9
-in the Software without restriction, including without limitation the rights
10
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
-copies of the Software, and to permit persons to whom the Software is
12
-furnished to do so, subject to the following conditions:
13
-
14
-The above copyright notice and this permission notice shall be included in all
15
-copies or substantial portions of the Software.
16
-
17
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
-SOFTWARE.
24
-*/
25
-
26
-//////////////////////////////////////////////////////////////////////////
27
-// Includes
28
-//////////////////////////////////////////////////////////////////////////
29
-#include <vector>
30
-#include <mutex>
31
-
32
-#include "amd-amf.h"
33
-#include "windows.h"
34
-
35
-// AMD AMF SDK
36
-#include "components\Component.h"
37
-#include "components\ComponentCaps.h"
38
-#include "components\VideoEncoderVCE.h"
39
-
40
-//////////////////////////////////////////////////////////////////////////
41
-// Code
42
-//////////////////////////////////////////////////////////////////////////
43
-using namespace Plugin::AMD;
44
-
45
-class CustomWriter : public amf::AMFTraceWriter {
46
-   public:
47
-   virtual void Write(const wchar_t* scope, const wchar_t* message) override {
48
-       const wchar_t* realmsg = &(message[(33 + wcslen(scope) + 2)]); // Skip Time & Scope
49
-       size_t msgLen = wcslen(realmsg) - (sizeof(wchar_t));
50
-
51
-       blog(LOG_INFO, "[%ls] %.*ls", scope, msgLen, realmsg);
52
-   }
53
-
54
-   virtual void Flush() override {}
55
-
56
-   static std::shared_ptr<CustomWriter> GetInstance() {
57
-       static std::shared_ptr<CustomWriter> __instance = std::make_shared<CustomWriter>();
58
-       static std::mutex __mutex;
59
-
60
-       const std::lock_guard<std::mutex> lock(__mutex);
61
-       return __instance;
62
-   }
63
-};
64
-
65
-std::shared_ptr<Plugin::AMD::AMF> Plugin::AMD::AMF::GetInstance() {
66
-   static std::shared_ptr<AMF> __instance = std::make_shared<AMF>();
67
-   static std::mutex __mutex;
68
-
69
-   const std::lock_guard<std::mutex> lock(__mutex);
70
-   return __instance;
71
-}
72
-
73
-Plugin::AMD::AMF::AMF() {
74
-   AMF_RESULT res = AMF_OK;
75
-
76
-   // Initialize AMF Library
77
-   AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> Initializing...");
78
-
79
-   #pragma region Null Class Members
80
-   m_TimerPeriod = 0;
81
-   m_AMFVersion_Compiler = 0;
82
-   m_AMFVersion_Runtime = 0;
83
-   m_AMFModule = 0;
84
-
85
-   m_AMFFactory = nullptr;
86
-   m_AMFTrace = nullptr;
87
-   m_AMFDebug = nullptr;
88
-   AMFQueryVersion = nullptr;
89
-   AMFInit = nullptr;
90
-   #pragma endregion Null Class Members
91
-
92
-   /// Load AMF Runtime into Memory.
93
-   m_AMFModule = LoadLibraryW(AMF_DLL_NAME);
94
-   if (!m_AMFModule) {
95
-       DWORD error = GetLastError();
96
-       std::vector<char> buf(1024);
97
-       sprintf(buf.data(), "Unable to load '%ls', error code %ld.", AMF_DLL_NAME, error);
98
-       AMF_LOG_ERROR("%s", buf.data());
99
-       throw std::exception(buf.data(), error);
100
-   }
101
-   AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> Loaded '%ls'.", AMF_DLL_NAME);
102
-   #ifdef _WIN32 // Windows: Get Product Version
103
-   std::vector<char> verbuf(GetFileVersionInfoSizeW(AMF_DLL_NAME, nullptr));
104
-   GetFileVersionInfoW(AMF_DLL_NAME, 0, (DWORD)verbuf.size(), verbuf.data());
105
-
106
-   void* pBlock = verbuf.data();
107
-
108
-   // Read the list of languages and code pages.
109
-   struct LANGANDCODEPAGE {
110
-       WORD wLanguage;
111
-       WORD wCodePage;
112
-   } *lpTranslate;
113
-   UINT cbTranslate = sizeof(LANGANDCODEPAGE);
114
-
115
-   VerQueryValueA(pBlock, "\\VarFileInfo\\Translation", (LPVOID*)&lpTranslate, &cbTranslate);
116
-
117
-   std::vector<char> buf(1024);
118
-   sprintf(buf.data(), "%s%04x%04x%s",
119
-       "\\StringFileInfo\\",
120
-       lpTranslate[0].wLanguage,
121
-       lpTranslate[0].wCodePage,
122
-       "\\ProductVersion");
123
-
124
-   // Retrieve file description for language and code page "i". 
125
-   void* lpBuffer;
126
-   uint32_t dwBytes;
127
-   VerQueryValueA(pBlock, buf.data(), &lpBuffer, &dwBytes);
128
-
129
-   AMF_LOG_INFO("Runtime Library is on Version %.*s.", dwBytes, lpBuffer);
130
-   #endif _WIN32 // Windows: Get Product Version
131
-
132
-   /// Find Function for Querying AMF Version.
133
-   #pragma region Query AMF Runtime Version
134
-   AMFQueryVersion = (AMFQueryVersion_Fn)GetProcAddress(m_AMFModule, AMF_QUERY_VERSION_FUNCTION_NAME);
135
-   if (!AMFQueryVersion) {
136
-       DWORD error = GetLastError();
137
-       std::vector<char> buf(1024);
138
-       sprintf(buf.data(), "<Plugin::AMD::AMF::AMF> Finding Address of Function '%s' failed with error code %ld.", AMF_QUERY_VERSION_FUNCTION_NAME, error);
139
-       AMF_LOG_ERROR("%s", buf.data());
140
-       throw std::exception(buf.data(), error);
141
-   }
142
-   /// Query Runtime Version
143
-   m_AMFVersion_Compiler = AMF_FULL_VERSION;
144
-   res = AMFQueryVersion(&m_AMFVersion_Runtime);
145
-   if (res != AMF_OK)
146
-       ThrowExceptionWithAMFError("<Plugin::AMD::AMF::AMF> Querying Version failed with error %ls (code %ld).", res);
147
-   /// Log some Information for Supporters.
148
-   AMF_LOG_INFO("Runtime is on Version %d.%d.%d.%d, compiled against Version %d.%d.%d.%d.",
149
-       (uint16_t)((m_AMFVersion_Runtime >> 48ull) & 0xFFFF),
150
-       (uint16_t)((m_AMFVersion_Runtime >> 32ull) & 0xFFFF),
151
-       (uint16_t)((m_AMFVersion_Runtime >> 16ull) & 0xFFFF),
152
-       (uint16_t)((m_AMFVersion_Runtime & 0xFFFF)),
153
-       (uint16_t)((m_AMFVersion_Compiler >> 48ull) & 0xFFFF),
154
-       (uint16_t)((m_AMFVersion_Compiler >> 32ull) & 0xFFFF),
155
-       (uint16_t)((m_AMFVersion_Compiler >> 16ull) & 0xFFFF),
156
-       (uint16_t)((m_AMFVersion_Compiler & 0xFFFF)));
157
-   #pragma endregion Query AMF Runtime Version
158
-
159
-       /// Find Function for Initializing AMF.
160
-   AMFInit = (AMFInit_Fn)GetProcAddress(m_AMFModule, AMF_INIT_FUNCTION_NAME);
161
-   if (!AMFInit) {
162
-       DWORD error = GetLastError();
163
-       std::vector<char> buf(1024);
164
-       sprintf(buf.data(), "<Plugin::AMD::AMF::AMF> Finding Address of Function '%s' failed with error code %ld.", AMF_INIT_FUNCTION_NAME, error);
165
-       AMF_LOG_ERROR("%s", buf.data());
166
-       throw std::exception(buf.data(), error);
167
-   } else {
168
-       res = AMFInit(m_AMFVersion_Runtime, &m_AMFFactory);
169
-       if (res != AMF_OK)
170
-           ThrowExceptionWithAMFError("<Plugin::AMD::AMF::AMF> Initializing AMF Library failed with error %ls (code %ld).", res);
171
-   }
172
-   AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> AMF Library initialized.");
173
-
174
-   /// Retrieve Trace Object.
175
-   res = m_AMFFactory->GetTrace(&m_AMFTrace);
176
-   if (res != AMF_OK) {
177
-       ThrowExceptionWithAMFError("<Plugin::AMD::AMF::AMF> Retrieving Trace object failed with error %ls (code %ld).", res);
178
-   }
179
-
180
-   /// Retrieve Debug Object.
181
-   res = m_AMFFactory->GetDebug(&m_AMFDebug);
182
-   if (res != AMF_OK) {
183
-       AMF_LOG_ERROR("<Plugin::AMD::AMF::AMF> Retrieving Debug object failed with error code %ls (code %ld).", res);
184
-       throw std::exception("", res);
185
-   }
186
-
187
-   /// Register Custom Trace Writer and disable Debug Tracing.
188
-   m_AMFTrace->RegisterWriter(L"OBSWriter", CustomWriter::GetInstance().get(), true);
189
-   this->EnableDebugTrace(false);
190
-
191
-   AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> Initialized.");
192
-}
193
-
194
-Plugin::AMD::AMF::~AMF() {
195
-   AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> Finalizing.");
196
-
197
-   /// Unregister Writer
198
-   if (m_AMFTrace)
199
-       m_AMFTrace->UnregisterWriter(L"OBSWriter");
200
-
201
-   // Free Library again
202
-   if (m_AMFModule)
203
-       FreeLibrary(m_AMFModule);
204
-
205
-   #pragma region Null Class Members
206
-   m_TimerPeriod = 0;
207
-   m_AMFVersion_Compiler = 0;
208
-   m_AMFVersion_Runtime = 0;
209
-   m_AMFModule = 0;
210
-
211
-   m_AMFFactory = nullptr;
212
-   m_AMFTrace = nullptr;
213
-   m_AMFDebug = nullptr;
214
-   AMFQueryVersion = nullptr;
215
-   AMFInit = nullptr;
216
-   #pragma endregion Null Class Members
217
-
218
-   AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> Finalized.");
219
-}
220
-
221
-amf::AMFFactory* Plugin::AMD::AMF::GetFactory() {
222
-   return m_AMFFactory;
223
-}
224
-
225
-amf::AMFTrace* Plugin::AMD::AMF::GetTrace() {
226
-   return m_AMFTrace;
227
-}
228
-
229
-amf::AMFDebug* Plugin::AMD::AMF::GetDebug() {
230
-   return m_AMFDebug;
231
-}
232
-
233
-void Plugin::AMD::AMF::EnableDebugTrace(bool enable) {
234
-   if (!m_AMFTrace)
235
-       throw std::exception(__FUNCTION_NAME__ " called without a AMFTrace object!");
236
-   if (!m_AMFDebug)
237
-       throw std::exception(__FUNCTION_NAME__ " called without a AMFDebug object!");
238
-
239
-   m_AMFTrace->EnableWriter(AMF_TRACE_WRITER_CONSOLE, false);
240
-   m_AMFTrace->SetWriterLevel(AMF_TRACE_WRITER_CONSOLE, AMF_TRACE_ERROR);
241
-   #ifdef DEBUG
242
-   m_AMFTrace->EnableWriter(AMF_TRACE_WRITER_DEBUG_OUTPUT, true);
243
-   m_AMFTrace->SetWriterLevel(AMF_TRACE_WRITER_DEBUG_OUTPUT, AMF_TRACE_TEST);
244
-   m_AMFTrace->SetPath(L"C:/AMFTrace.log");
245
-   #else
246
-   m_AMFTrace->EnableWriter(AMF_TRACE_WRITER_DEBUG_OUTPUT, false);
247
-   m_AMFTrace->SetWriterLevel(AMF_TRACE_WRITER_DEBUG_OUTPUT, AMF_TRACE_ERROR);
248
-   #endif
249
-   m_AMFTrace->EnableWriter(AMF_TRACE_WRITER_FILE, false);
250
-   m_AMFTrace->SetWriterLevel(AMF_TRACE_WRITER_FILE, AMF_TRACE_ERROR);
251
-
252
-   if (enable) {
253
-       m_AMFDebug->AssertsEnable(true);
254
-       m_AMFDebug->EnablePerformanceMonitor(true);
255
-       m_AMFTrace->TraceEnableAsync(true);
256
-       m_AMFTrace->SetGlobalLevel(AMF_TRACE_TEST);
257
-       m_AMFTrace->SetWriterLevel(L"OBSWriter", AMF_TRACE_TEST);
258
-   } else {
259
-       m_AMFDebug->AssertsEnable(false);
260
-       m_AMFDebug->EnablePerformanceMonitor(false);
261
-       m_AMFTrace->TraceEnableAsync(true);
262
-       m_AMFTrace->SetGlobalLevel(AMF_TRACE_WARNING);
263
-       m_AMFTrace->SetWriterLevel(L"OBSWriter", AMF_TRACE_WARNING);
264
-   }
265
-}
266
obs-studio-0.16.6.tar.xz/plugins/obs-filters/color-filter.c Deleted
176
 
1
@@ -1,174 +0,0 @@
2
-#include <obs-module.h>
3
-#include <graphics/vec4.h>
4
-
5
-#define SETTING_COLOR                  "color"
6
-#define SETTING_OPACITY                "opacity"
7
-#define SETTING_CONTRAST               "contrast"
8
-#define SETTING_BRIGHTNESS             "brightness"
9
-#define SETTING_GAMMA                  "gamma"
10
-
11
-#define TEXT_COLOR                     obs_module_text("Color")
12
-#define TEXT_OPACITY                   obs_module_text("Opacity")
13
-#define TEXT_CONTRAST                  obs_module_text("Contrast")
14
-#define TEXT_BRIGHTNESS                obs_module_text("Brightness")
15
-#define TEXT_GAMMA                     obs_module_text("Gamma")
16
-
17
-#define MIN_CONTRAST 0.5f
18
-#define MAX_CONTRAST 2.0f
19
-#define MIN_BRIGHTNESS -1.0
20
-#define MAX_BRIGHTNESS 1.0
21
-
22
-struct color_filter_data {
23
-   obs_source_t                   *context;
24
-
25
-   gs_effect_t                    *effect;
26
-
27
-   gs_eparam_t                    *color_param;
28
-   gs_eparam_t                    *contrast_param;
29
-   gs_eparam_t                    *brightness_param;
30
-   gs_eparam_t                    *gamma_param;
31
-
32
-   struct vec4                    color;
33
-   float                          contrast;
34
-   float                          brightness;
35
-   float                          gamma;
36
-};
37
-
38
-static const char *color_filter_name(void *unused)
39
-{
40
-   UNUSED_PARAMETER(unused);
41
-   return obs_module_text("ColorFilter");
42
-}
43
-
44
-static void color_filter_update(void *data, obs_data_t *settings)
45
-{
46
-   struct color_filter_data *filter = data;
47
-   uint32_t color = (uint32_t)obs_data_get_int(settings, SETTING_COLOR);
48
-   uint32_t opacity = (uint32_t)obs_data_get_int(settings,
49
-           SETTING_OPACITY);
50
-   double contrast = obs_data_get_double(settings, SETTING_CONTRAST);
51
-   double brightness = obs_data_get_double(settings, SETTING_BRIGHTNESS);
52
-   double gamma = obs_data_get_double(settings, SETTING_GAMMA);
53
-
54
-   color &= 0xFFFFFF;
55
-   color |= ((opacity * 255) / 100) << 24;
56
-
57
-   vec4_from_rgba(&filter->color, color);
58
-
59
-   contrast = (contrast < 0.0) ?
60
-       (1.0 / (-contrast + 1.0)) : (contrast + 1.0);
61
-
62
-   brightness *= 0.5;
63
-
64
-   gamma = (gamma < 0.0) ? (-gamma + 1.0) : (1.0 / (gamma + 1.0));
65
-
66
-   filter->contrast = (float)contrast;
67
-   filter->brightness = (float)brightness;
68
-   filter->gamma = (float)gamma;
69
-}
70
-
71
-static void color_filter_destroy(void *data)
72
-{
73
-   struct color_filter_data *filter = data;
74
-
75
-   if (filter->effect) {
76
-       obs_enter_graphics();
77
-       gs_effect_destroy(filter->effect);
78
-       obs_leave_graphics();
79
-   }
80
-
81
-   bfree(data);
82
-}
83
-
84
-static void *color_filter_create(obs_data_t *settings, obs_source_t *context)
85
-{
86
-   struct color_filter_data *filter =
87
-       bzalloc(sizeof(struct color_filter_data));
88
-   char *effect_path = obs_module_file("color_filter.effect");
89
-
90
-   filter->context = context;
91
-
92
-   obs_enter_graphics();
93
-
94
-   filter->effect = gs_effect_create_from_file(effect_path, NULL);
95
-   if (filter->effect) {
96
-       filter->color_param = gs_effect_get_param_by_name(
97
-               filter->effect, "color");
98
-       filter->contrast_param = gs_effect_get_param_by_name(
99
-               filter->effect, "contrast");
100
-       filter->brightness_param = gs_effect_get_param_by_name(
101
-               filter->effect, "brightness");
102
-       filter->gamma_param = gs_effect_get_param_by_name(
103
-               filter->effect, "gamma");
104
-   }
105
-
106
-   obs_leave_graphics();
107
-
108
-   bfree(effect_path);
109
-
110
-   if (!filter->effect) {
111
-       color_filter_destroy(filter);
112
-       return NULL;
113
-   }
114
-
115
-   color_filter_update(filter, settings);
116
-   return filter;
117
-}
118
-
119
-static void color_filter_render(void *data, gs_effect_t *effect)
120
-{
121
-   struct color_filter_data *filter = data;
122
-
123
-   if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
124
-               OBS_ALLOW_DIRECT_RENDERING))
125
-       return;
126
-
127
-   gs_effect_set_vec4(filter->color_param, &filter->color);
128
-   gs_effect_set_float(filter->contrast_param, filter->contrast);
129
-   gs_effect_set_float(filter->brightness_param, filter->brightness);
130
-   gs_effect_set_float(filter->gamma_param, filter->gamma);
131
-
132
-   obs_source_process_filter_end(filter->context, filter->effect, 0, 0);
133
-
134
-   UNUSED_PARAMETER(effect);
135
-}
136
-
137
-static obs_properties_t *color_filter_properties(void *data)
138
-{
139
-   obs_properties_t *props = obs_properties_create();
140
-
141
-   obs_properties_add_color(props, SETTING_COLOR, TEXT_COLOR);
142
-   obs_properties_add_int(props, SETTING_OPACITY, TEXT_OPACITY,
143
-           0, 100, 1);
144
-   obs_properties_add_float_slider(props, SETTING_CONTRAST,
145
-           TEXT_CONTRAST, -1.0, 1.0, 0.01);
146
-   obs_properties_add_float_slider(props, SETTING_BRIGHTNESS,
147
-           TEXT_BRIGHTNESS, -1.0, 1.0, 0.01);
148
-   obs_properties_add_float_slider(props, SETTING_GAMMA,
149
-           TEXT_GAMMA, -1.0, 1.0, 0.01);
150
-
151
-   UNUSED_PARAMETER(data);
152
-   return props;
153
-}
154
-
155
-static void color_filter_defaults(obs_data_t *settings)
156
-{
157
-   obs_data_set_default_int(settings, SETTING_COLOR, 0xFFFFFF);
158
-   obs_data_set_default_int(settings, SETTING_OPACITY, 100);
159
-   obs_data_set_default_double(settings, SETTING_CONTRAST, 0.0);
160
-   obs_data_set_default_double(settings, SETTING_BRIGHTNESS, 0.0);
161
-   obs_data_set_default_double(settings, SETTING_GAMMA, 0.0);
162
-}
163
-
164
-struct obs_source_info color_filter = {
165
-   .id                            = "color_filter",
166
-   .type                          = OBS_SOURCE_TYPE_FILTER,
167
-   .output_flags                  = OBS_SOURCE_VIDEO,
168
-   .get_name                      = color_filter_name,
169
-   .create                        = color_filter_create,
170
-   .destroy                       = color_filter_destroy,
171
-   .video_render                  = color_filter_render,
172
-   .update                        = color_filter_update,
173
-   .get_properties                = color_filter_properties,
174
-   .get_defaults                  = color_filter_defaults
175
-};
176
obs-studio-0.16.6.tar.xz/plugins/obs-filters/data/color_filter.effect Deleted
48
 
1
@@ -1,46 +0,0 @@
2
-uniform float4x4 ViewProj;
3
-uniform texture2d image;
4
-
5
-uniform float4 color;
6
-uniform float contrast;
7
-uniform float brightness;
8
-uniform float gamma;
9
-
10
-sampler_state textureSampler {
11
-   Filter    = Linear;
12
-   AddressU  = Clamp;
13
-   AddressV  = Clamp;
14
-};
15
-
16
-struct VertData {
17
-   float4 pos : POSITION;
18
-   float2 uv  : TEXCOORD0;
19
-};
20
-
21
-VertData VSDefault(VertData v_in)
22
-{
23
-   VertData vert_out;
24
-   vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj);
25
-   vert_out.uv  = v_in.uv;
26
-   return vert_out;
27
-}
28
-
29
-float4 CalcColor(float4 rgba)
30
-{
31
-   return float4(pow(rgba.rgb, float3(gamma, gamma, gamma)) * contrast + brightness, rgba.a);
32
-}
33
-
34
-float4 PSColorFilterRGBA(VertData v_in) : TARGET
35
-{
36
-   float4 rgba = image.Sample(textureSampler, v_in.uv) * color;
37
-   return CalcColor(rgba);
38
-}
39
-
40
-technique Draw
41
-{
42
-   pass
43
-   {
44
-       vertex_shader = VSDefault(v_in);
45
-       pixel_shader  = PSColorFilterRGBA(v_in);
46
-   }
47
-}
48
obs-studio-0.16.6.tar.xz/.travis.yml -> obs-studio-0.17.0.tar.xz/.travis.yml Changed
22
 
1
@@ -1,5 +1,4 @@
2
 os: osx
3
-osx_image: xcode7.1
4
 env:
5
   matrix:
6
   - CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake
7
@@ -9,14 +8,11 @@
8
   - secure: "MfhOg+84yb4ZHB2tM8PIPFQX2Y+WLN0I0iiAgyLC4KaHPUoNOyloe9yk6OjV7Lj7SZWqTlQUsqHa8S9mOUswGIody1Ydglo4RvyGOKCd8I6b2ri/jE8qHVuD9sO+sNlIxq4YqqG/qReTsbSs2YEgLneZUCYLCk/fihl8L6eVuSc="
9
   # secret
10
   - secure: "JRQVU2zgC3hY6CEY+Crmh/upp93En0BzKaLcsuBT538johNlK7m5hn3m2UOw63seLvBvVaKKWUDj9N986a3DwcXxWPMyF/9ctXgNWy39WzaVWxrbVR5nQB1fdiRp5YEgkoVN+gEm3OVF7sV5AGzh5/8CvEdRCoTLIGgMGHxW9mc="
11
-
12
 language: cpp
13
-
14
 before_install: "./CI/install-dependencies-osx.sh"
15
 before_script: "./CI/before-script-osx.sh"
16
 script: cd ./build && make -j4 && cd -
17
 before_deploy: "./CI/before-deploy-osx.sh"
18
-
19
 deploy:
20
   provider: s3
21
   access_key_id: $AWS_ACCESS_KEY
22
obs-studio-0.16.6.tar.xz/CI/install-dependencies-osx.sh -> obs-studio-0.17.0.tar.xz/CI/install-dependencies-osx.sh Changed
10
 
1
@@ -1,7 +1,7 @@
2
 brew update
3
 
4
 #Base OBS Deps
5
-brew install ffmpeg x264 qt5 python cmake
6
+brew install ffmpeg x264 qt5
7
 
8
 # CEF Stuff
9
 cd ../
10
obs-studio-0.16.6.tar.xz/CMakeLists.txt -> obs-studio-0.17.0.tar.xz/CMakeLists.txt Changed
19
 
1
@@ -2,6 +2,8 @@
2
 
3
 project(obs-studio)
4
 
5
+option(BUILD_CAPTIONS "Build captions" FALSE)
6
+
7
 if(WIN32)
8
    if (QTDIR OR DEFINED ENV{QTDIR} OR DEFINED ENV{QTDIR32} OR DEFINED ENV{QTDIR64})
9
        # Qt path set by user or env var
10
@@ -60,7 +62,7 @@
11
 endif()
12
 
13
 if(WIN32)
14
-   add_definitions(-DUNICODE -D_UNICODE)
15
+   add_definitions(-DUNICODE -D_UNICODE -D_CRT_SECURE_NO_WARNINGS)
16
 endif()
17
 
18
 if(MSVC)
19
obs-studio-0.16.6.tar.xz/UI/adv-audio-control.cpp -> obs-studio-0.17.0.tar.xz/UI/adv-audio-control.cpp Changed
64
 
1
@@ -35,6 +35,8 @@
2
    mixer2                         = new QCheckBox();
3
    mixer3                         = new QCheckBox();
4
    mixer4                         = new QCheckBox();
5
+   mixer5                         = new QCheckBox();
6
+   mixer6                         = new QCheckBox();
7
 
8
    volChangedSignal.Connect(handler, "volume", OBSSourceVolumeChanged,
9
            this);
10
@@ -93,6 +95,10 @@
11
    mixer3->setChecked(mixers & (1<<2));
12
    mixer4->setText("4");
13
    mixer4->setChecked(mixers & (1<<3));
14
+   mixer5->setText("5");
15
+   mixer5->setChecked(mixers & (1<<4));
16
+   mixer6->setText("6");
17
+   mixer6->setChecked(mixers & (1<<5));
18
 
19
    panningContainer->layout()->addWidget(labelL);
20
    panningContainer->layout()->addWidget(panning);
21
@@ -103,6 +109,8 @@
22
    mixerContainer->layout()->addWidget(mixer2);
23
    mixerContainer->layout()->addWidget(mixer3);
24
    mixerContainer->layout()->addWidget(mixer4);
25
+   mixerContainer->layout()->addWidget(mixer5);
26
+   mixerContainer->layout()->addWidget(mixer6);
27
 
28
    QWidget::connect(volume, SIGNAL(valueChanged(int)),
29
            this, SLOT(volumeChanged(int)));
30
@@ -120,6 +128,10 @@
31
            this, SLOT(mixer3Changed(bool)));
32
    QWidget::connect(mixer4, SIGNAL(clicked(bool)),
33
            this, SLOT(mixer4Changed(bool)));
34
+   QWidget::connect(mixer5, SIGNAL(clicked(bool)),
35
+           this, SLOT(mixer5Changed(bool)));
36
+   QWidget::connect(mixer6, SIGNAL(clicked(bool)),
37
+           this, SLOT(mixer6Changed(bool)));
38
 
39
    int lastRow = layout->rowCount();
40
 
41
@@ -209,6 +221,8 @@
42
    setCheckboxState(mixer2, mixers & (1<<1));
43
    setCheckboxState(mixer3, mixers & (1<<2));
44
    setCheckboxState(mixer4, mixers & (1<<3));
45
+   setCheckboxState(mixer5, mixers & (1<<4));
46
+   setCheckboxState(mixer6, mixers & (1<<5));
47
 }
48
 
49
 /* ------------------------------------------------------------------------- */
50
@@ -281,3 +295,13 @@
51
 {
52
    setMixer(source, 3, checked);
53
 }
54
+
55
+void OBSAdvAudioCtrl::mixer5Changed(bool checked)
56
+{
57
+   setMixer(source, 4, checked);
58
+}
59
+
60
+void OBSAdvAudioCtrl::mixer6Changed(bool checked)
61
+{
62
+   setMixer(source, 5, checked);
63
+}
64
obs-studio-0.16.6.tar.xz/UI/adv-audio-control.hpp -> obs-studio-0.17.0.tar.xz/UI/adv-audio-control.hpp Changed
17
 
1
@@ -31,6 +31,8 @@
2
    QPointer<QCheckBox>    mixer2;
3
    QPointer<QCheckBox>    mixer3;
4
    QPointer<QCheckBox>    mixer4;
5
+   QPointer<QCheckBox>    mixer5;
6
+   QPointer<QCheckBox>    mixer6;
7
 
8
    OBSSignal              volChangedSignal;
9
    OBSSignal              syncOffsetSignal;
10
@@ -62,4 +64,6 @@
11
    void mixer2Changed(bool checked);
12
    void mixer3Changed(bool checked);
13
    void mixer4Changed(bool checked);
14
+   void mixer5Changed(bool checked);
15
+   void mixer6Changed(bool checked);
16
 };
17
obs-studio-0.16.6.tar.xz/UI/api-interface.cpp -> obs-studio-0.17.0.tar.xz/UI/api-interface.cpp Changed
37
 
1
@@ -234,6 +234,21 @@
2
        return main->outputHandler->RecordingActive();
3
    }
4
 
5
+   void obs_frontend_replay_buffer_start(void) override
6
+   {
7
+       QMetaObject::invokeMethod(main, "StartReplayBuffer");
8
+   }
9
+
10
+   void obs_frontend_replay_buffer_stop(void) override
11
+   {
12
+       QMetaObject::invokeMethod(main, "StopReplayBuffer");
13
+   }
14
+
15
+   bool obs_frontend_replay_buffer_active(void) override
16
+   {
17
+       return main->outputHandler->ReplayBufferActive();
18
+   }
19
+
20
    void *obs_frontend_add_tools_menu_qaction(const char *name) override
21
    {
22
        main->ui->menuTools->setEnabled(true);
23
@@ -286,6 +301,13 @@
24
        return out;
25
    }
26
 
27
+   obs_output_t *obs_frontend_get_replay_buffer_output(void) override
28
+   {
29
+       OBSOutput out = main->outputHandler->replayBuffer;
30
+       obs_output_addref(out);
31
+       return out;
32
+   }
33
+
34
    config_t *obs_frontend_get_profile_config(void) override
35
    {
36
        return main->basicConfig;
37
obs-studio-0.16.6.tar.xz/UI/data/locale/ar-SA.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/ar-SA.ini Changed
9
 
1
@@ -58,7 +58,6 @@
2
 QuickTransitions.HotkeyName="الانتقال السريع: %1"
3
 
4
 Basic.AddTransition="إضافة المراحل الانتقالية للتكوين"
5
-Basic.RemoveTransition="سلاو"
6
 Basic.TransitionProperties="خصائص تأثير الإنتقال"
7
 Basic.SceneTransitions="تأثير انتقال المشهد"
8
 Basic.TransitionDuration="مدة الانتقال"
9
obs-studio-0.16.6.tar.xz/UI/data/locale/bg-BG.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/bg-BG.ini Changed
12
 
1
@@ -284,10 +284,6 @@
2
 
3
 Basic.Settings.Hotkeys="Горещи клавиши"
4
 
5
-Basic.Hotkeys.StartStreaming="Започни стрийм"
6
-Basic.Hotkeys.StopStreaming="Спри стрийм"
7
-Basic.Hotkeys.StartRecording="Започни запис"
8
-Basic.Hotkeys.StopRecording="Спри запис"
9
 Basic.Hotkeys.SelectScene="Премини към сцена"
10
 
11
 
12
obs-studio-0.16.6.tar.xz/UI/data/locale/ca-ES.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/ca-ES.ini Changed
12
 
1
@@ -492,10 +492,6 @@
2
 Basic.Settings.Hotkeys="Dreceres de teclat"
3
 Basic.Settings.Hotkeys.Pair="Combinacions de tecles compartides amb '%1' actuen com a palanques"
4
 
5
-Basic.Hotkeys.StartStreaming="Inicia el directe"
6
-Basic.Hotkeys.StopStreaming="Atura el directe"
7
-Basic.Hotkeys.StartRecording="Inicia l'enregistrament"
8
-Basic.Hotkeys.StopRecording="Atura l'enregistrament"
9
 Basic.Hotkeys.SelectScene="Canviar a escena"
10
 
11
 Basic.SystemTray.Show="Mostra"
12
obs-studio-0.16.6.tar.xz/UI/data/locale/cs-CZ.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/cs-CZ.ini Changed
81
 
1
@@ -53,6 +53,9 @@
2
 Minutes="Minuty"
3
 Seconds="Vteřiny"
4
 Deprecated="Zastaralé"
5
+ReplayBuffer="Záznam do paměti"
6
+Import="Importovat"
7
+Export="Exportovat"
8
 
9
 QuickTransitions.SwapScenes="Prohodit scény náhledu a výstupu po přechodu"
10
 QuickTransitions.SwapScenesTT="Prohodí scény náhledu a výstupu po přechodu (pokud originální výstupní scéna stále existuje).\nTato funkce nevrátí provedené změny, které byly provedeny v originální scéně výstupu."
11
@@ -107,6 +110,8 @@
12
 Output.RecordNoSpace.Msg="Pro pokračování nahrávání není dostatek místa na disku."
13
 Output.RecordError.Title="Chyba při nahrávání"
14
 Output.RecordError.Msg="Při nahrávání došlo k nespecifikované chybě."
15
+Output.ReplayBuffer.NoHotkey.Title="Nepřiřazena žádná klávesová zkratka!"
16
+Output.ReplayBuffer.NoHotkey.Msg="Není nastavena žádná klávesová zkratka pro uložení záznamu. Nastavte ji prosím, abyste jej mohli ukládat."
17
 
18
 Output.BadPath.Title="Špatná cesta k souboru"
19
 Output.BadPath.Text="Nastavená cesta k výstupnímu souboru je chybná. Zkontrolujte nastavení, zda není cesta špatně napsána."
20
@@ -262,9 +267,12 @@
21
 Basic.Main.Sources="Zdroje"
22
 Basic.Main.Connecting="Připojování..."
23
 Basic.Main.StartRecording="Začít nahrávat"
24
+Basic.Main.StartReplayBuffer="Spustit záznam do paměti"
25
 Basic.Main.StartStreaming="Začít vysílat"
26
 Basic.Main.StopRecording="Zastavit nahrávání"
27
 Basic.Main.StoppingRecording="Zastavuji nahrávání..."
28
+Basic.Main.StopReplayBuffer="Zastavit záznam do paměti"
29
+Basic.Main.StoppingReplayBuffer="Zastavuji záznam do paměti..."
30
 Basic.Main.StopStreaming="Zastavit vysílání"
31
 Basic.Main.StoppingStreaming="Zastavuji vysílání..."
32
 Basic.Main.ForceStopStreaming="Zastavit vysání (bez zpoždění)"
33
@@ -292,6 +300,8 @@
34
 Basic.MainMenu.Edit.Scale.Output="Výstup (%1x%2)"
35
 Basic.MainMenu.Edit.Transform="Pozicování (&T)"
36
 Basic.MainMenu.Edit.Transform.EditTransform="Upravit pozici... (&E)"
37
+Basic.MainMenu.Edit.Transform.CopyTransform="Kopírovat transformaci"
38
+Basic.MainMenu.Edit.Transform.PasteTransform="Vložit transformaci"
39
 Basic.MainMenu.Edit.Transform.ResetTransform="Obnovit pozici (&R)"
40
 Basic.MainMenu.Edit.Transform.Rotate90CW="Otočit o 90 stupňů vpravo"
41
 Basic.MainMenu.Edit.Transform.Rotate90CCW="Otočit o 90 stupňů vlevo"
42
@@ -316,6 +326,12 @@
43
 
44
 Basic.MainMenu.SceneCollection="Kolekce &scén"
45
 Basic.MainMenu.Profile="&Profil"
46
+Basic.MainMenu.Profile.Import="Importovat profil"
47
+Basic.MainMenu.Profile.Export="Exportovat profil"
48
+Basic.MainMenu.SceneCollection.Import="Importovat kolekci scén"
49
+Basic.MainMenu.SceneCollection.Export="Exportovat kolekci scén"
50
+Basic.MainMenu.Profile.Exists="Tento profil již existuje"
51
+Basic.MainMenu.SceneCollection.Exists="Tato kolekce scén již existuje"
52
 
53
 Basic.MainMenu.Tools="Nás&troje"
54
 
55
@@ -362,6 +378,14 @@
56
 Basic.Settings.Output.Mode.Simple="Jednoduché"
57
 Basic.Settings.Output.Mode.Adv="Rozšířené"
58
 Basic.Settings.Output.Mode.FFmpeg="Výstup FFmpeg"
59
+Basic.Settings.Output.UseReplayBuffer="Povolit záznam od paměti"
60
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Maximální čas záznamu (s)"
61
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Maximální využití paměti (MB)"
62
+Basic.Settings.Output.ReplayBuffer.Estimate="Přibližné využití paměti: %1 MB"
63
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Nedokáži odhadnout využití paměti. Nastavte, prosím, maximální využití paměti."
64
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Poznámka: Nezapomeňte si nastavit klávesovou zkratku pro tuto funkci)"
65
+Basic.Settings.Output.ReplayBuffer.Prefix="Přípona souboru záznamu do paměti"
66
+Basic.Settings.Output.ReplayBuffer.Suffix="Přípona"
67
 Basic.Settings.Output.Simple.SavePath="Cesta pro nahrávání"
68
 Basic.Settings.Output.Simple.RecordingQuality="Nahrávací kvalita"
69
 Basic.Settings.Output.Simple.RecordingQuality.Stream="Stejná jako vysílaná"
70
@@ -497,10 +521,6 @@
71
 Basic.Settings.Hotkeys="Zkratky"
72
 Basic.Settings.Hotkeys.Pair="Kombinace kláves je sdílená s '%1' funguje jako přepínač"
73
 
74
-Basic.Hotkeys.StartStreaming="Začít vysílat"
75
-Basic.Hotkeys.StopStreaming="Zastavit vysílání"
76
-Basic.Hotkeys.StartRecording="Začít nahrávat"
77
-Basic.Hotkeys.StopRecording="Zastavit nahrávání"
78
 Basic.Hotkeys.SelectScene="Přepnout na scénu"
79
 
80
 Basic.SystemTray.Show="Zobrazit"
81
obs-studio-0.16.6.tar.xz/UI/data/locale/da-DK.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/da-DK.ini Changed
81
 
1
@@ -53,6 +53,9 @@
2
 Minutes="Minutter"
3
 Seconds="Sekunder"
4
 Deprecated="Ophørt"
5
+ReplayBuffer="Genafspilningsbuffer"
6
+Import="Importér"
7
+Export="Eksportér"
8
 
9
 QuickTransitions.SwapScenes="Byt om på forhåndsvisning/output scener efter overgang"
10
 QuickTransitions.SwapScenesTT="Ombytter uddrag- og output-scener efter omskiftning (hvis oprindelige output-scene stadig eksisterer).\nDette vil ikke omgøre eventuelle ændringer, der måtte været udført på den oprindelige output-scene."
11
@@ -107,6 +110,8 @@
12
 Output.RecordNoSpace.Msg="Der er ikke tilstrækkelig diskplads til at fortsætte optagelsen."
13
 Output.RecordError.Title="Optagelsesfejl"
14
 Output.RecordError.Msg="Der opstod en uangivet fejl under optagelsen."
15
+Output.ReplayBuffer.NoHotkey.Title="Ingen genvejstast sat!"
16
+Output.ReplayBuffer.NoHotkey.Msg="Ingen Gem-genvejstast sat til genafspilningsbuffer. Sæt venligst \"Gem\"-genvejstasten til brug for at gemme genafspilningsoptagelser."
17
 
18
 Output.BadPath.Title="Dårlig filsti"
19
 Output.BadPath.Text="Den konfigureret output sti er ugyldig. Kontroller indstillinger for at bekræfte, at en gyldig filsti er angivet."
20
@@ -262,9 +267,12 @@
21
 Basic.Main.Sources="Kilder"
22
 Basic.Main.Connecting="Forbinder..."
23
 Basic.Main.StartRecording="Start optagelse"
24
+Basic.Main.StartReplayBuffer="Start Genafspilningsbuffer"
25
 Basic.Main.StartStreaming="Start streaming"
26
 Basic.Main.StopRecording="Stop optagelse"
27
 Basic.Main.StoppingRecording="Stopper optagelse..."
28
+Basic.Main.StopReplayBuffer="Stop Genafspilningsbuffer"
29
+Basic.Main.StoppingReplayBuffer="Stopper Genafspilningsbuffer..."
30
 Basic.Main.StopStreaming="Stop streaming"
31
 Basic.Main.StoppingStreaming="Stopper stream..."
32
 Basic.Main.ForceStopStreaming="Stop streaming (ignorer forsinkelse)"
33
@@ -292,6 +300,8 @@
34
 Basic.MainMenu.Edit.Scale.Output="Output (%1x%2)"
35
 Basic.MainMenu.Edit.Transform="&Transformering"
36
 Basic.MainMenu.Edit.Transform.EditTransform="Rediger transformering... (&E)"
37
+Basic.MainMenu.Edit.Transform.CopyTransform="Kopiér transformation"
38
+Basic.MainMenu.Edit.Transform.PasteTransform="Indsæt transformation"
39
 Basic.MainMenu.Edit.Transform.ResetTransform="Nulstille transformering (&R)"
40
 Basic.MainMenu.Edit.Transform.Rotate90CW="Roter 90 grader CW"
41
 Basic.MainMenu.Edit.Transform.Rotate90CCW="Roter 90 grader CCW"
42
@@ -316,6 +326,12 @@
43
 
44
 Basic.MainMenu.SceneCollection="&Scenesamling"
45
 Basic.MainMenu.Profile="&Profil"
46
+Basic.MainMenu.Profile.Import="Importér profil"
47
+Basic.MainMenu.Profile.Export="Eksportér profil"
48
+Basic.MainMenu.SceneCollection.Import="Importér scenesamling"
49
+Basic.MainMenu.SceneCollection.Export="Eksportér scenesamling"
50
+Basic.MainMenu.Profile.Exists="Profilen findes allerede"
51
+Basic.MainMenu.SceneCollection.Exists="Scenesamlingen findes allerede"
52
 
53
 Basic.MainMenu.Tools="Værk&tøjer"
54
 
55
@@ -362,6 +378,14 @@
56
 Basic.Settings.Output.Mode.Simple="Simpel"
57
 Basic.Settings.Output.Mode.Adv="Avanceret"
58
 Basic.Settings.Output.Mode.FFmpeg="FFmpeg output"
59
+Basic.Settings.Output.UseReplayBuffer="Aktivér Genafspilningsbuffer"
60
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Maksimal genafspilningstid (sek.)"
61
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Maksimal hukommelse (MB)"
62
+Basic.Settings.Output.ReplayBuffer.Estimate="Anslået hukommelsesforbrug: %1 MB"
63
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Ikke kan beregne hukommelsesforbrug. Sæt venligst maks. hukommelsesgrænse."
64
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Bemærk: Sørg for at sætte en genvejstast til genafspilningsbufferen i sektionen for genvejstaster)"
65
+Basic.Settings.Output.ReplayBuffer.Prefix="Genafspilningsbuffer filnavn præfiks"
66
+Basic.Settings.Output.ReplayBuffer.Suffix="Endelse"
67
 Basic.Settings.Output.Simple.SavePath="Optagelsessti"
68
 Basic.Settings.Output.Simple.RecordingQuality="Optagelseskvalitet"
69
 Basic.Settings.Output.Simple.RecordingQuality.Stream="Samme som stream"
70
@@ -497,10 +521,6 @@
71
 Basic.Settings.Hotkeys="Genvejstaster"
72
 Basic.Settings.Hotkeys.Pair="Tastekombinationer delt med '%1' fungerer som omskiftere"
73
 
74
-Basic.Hotkeys.StartStreaming="Start streaming"
75
-Basic.Hotkeys.StopStreaming="Stop streaming"
76
-Basic.Hotkeys.StartRecording="Start optagelse"
77
-Basic.Hotkeys.StopRecording="Stop optagelse"
78
 Basic.Hotkeys.SelectScene="Skift til scene"
79
 
80
 Basic.SystemTray.Show="Vis"
81
obs-studio-0.16.6.tar.xz/UI/data/locale/de-DE.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/de-DE.ini Changed
90
 
1
@@ -53,6 +53,9 @@
2
 Minutes="Minute(n)"
3
 Seconds="Sekunde(n)"
4
 Deprecated="Veraltet"
5
+ReplayBuffer="Replaypuffer"
6
+Import="Importieren"
7
+Export="Exportieren"
8
 
9
 QuickTransitions.SwapScenes="Tausche Vorschau/Ausgabe-Szenen nach dem Übergang"
10
 QuickTransitions.SwapScenesTT="Vertauscht die Vorschau- und Ausgabe-Szenen nach dem Übergang (falls die ursprüngliche Ausgabe-Szene noch vorhanden ist).\nEventuelle Änderungen an der original Ausgabe-Szene werden hierbei nicht rückgängig gemacht."
11
@@ -107,6 +110,8 @@
12
 Output.RecordNoSpace.Msg="Es gibt nicht genügend Speicherplatz, um die Aufnahme fortzusetzen."
13
 Output.RecordError.Title="Aufnahmefehler"
14
 Output.RecordError.Msg="Während der Aufnahme ist ein unbekannter Fehler aufgetreten."
15
+Output.ReplayBuffer.NoHotkey.Title="Kein Hotkey festgelegt!"
16
+Output.ReplayBuffer.NoHotkey.Msg="Kein Speichern Hotkey festgelegt für Replaypuffer. Legen Sie bitte den \"Speichern\" Hotkey fest, der zum Speichern der Replayaufnahmen verwendet werden soll."
17
 
18
 Output.BadPath.Title="Ungültiger Dateipfad"
19
 Output.BadPath.Text="Der konfigurierte Ausgabepfad ist ungültig. Bitte überprüfen Sie Ihre Einstellungen und stellen Sie sicher, dass ein gültiger Pfad angegeben wurde."
20
@@ -262,9 +267,12 @@
21
 Basic.Main.Sources="Quellen"
22
 Basic.Main.Connecting="Verbinden..."
23
 Basic.Main.StartRecording="Aufnahme starten"
24
+Basic.Main.StartReplayBuffer="Replaypuffer starten"
25
 Basic.Main.StartStreaming="Streaming starten"
26
 Basic.Main.StopRecording="Aufnahme stoppen"
27
 Basic.Main.StoppingRecording="Stoppe Aufnahme..."
28
+Basic.Main.StopReplayBuffer="Replaypuffer stoppen"
29
+Basic.Main.StoppingReplayBuffer="Stoppe Replaypuffer..."
30
 Basic.Main.StopStreaming="Streaming stoppen"
31
 Basic.Main.StoppingStreaming="Stoppe Stream..."
32
 Basic.Main.ForceStopStreaming="Streaming stoppen (Verzögerung verwerfen)"
33
@@ -292,6 +300,8 @@
34
 Basic.MainMenu.Edit.Scale.Output="Ausgabe (%1x%2)"
35
 Basic.MainMenu.Edit.Transform="&Transformieren"
36
 Basic.MainMenu.Edit.Transform.EditTransform="Transformation b&earbeiten..."
37
+Basic.MainMenu.Edit.Transform.CopyTransform="Transformation kopieren"
38
+Basic.MainMenu.Edit.Transform.PasteTransform="Transformation einfügen"
39
 Basic.MainMenu.Edit.Transform.ResetTransform="Transformation zu&rücksetzen"
40
 Basic.MainMenu.Edit.Transform.Rotate90CW="Um 90° im Uhrzeigersinn drehen"
41
 Basic.MainMenu.Edit.Transform.Rotate90CCW="Um 90° gegen den Uhrzeigersinn drehen"
42
@@ -316,6 +326,12 @@
43
 
44
 Basic.MainMenu.SceneCollection="&Szenen-Sammlung"
45
 Basic.MainMenu.Profile="&Profil"
46
+Basic.MainMenu.Profile.Import="Profil importieren"
47
+Basic.MainMenu.Profile.Export="Profil exportieren"
48
+Basic.MainMenu.SceneCollection.Import="Szenen-Sammlung importieren"
49
+Basic.MainMenu.SceneCollection.Export="Szenen-Sammlung exportieren"
50
+Basic.MainMenu.Profile.Exists="Das Profil ist bereits vorhanden"
51
+Basic.MainMenu.SceneCollection.Exists="Die Szenen-Sammlung existiert bereits"
52
 
53
 Basic.MainMenu.Tools="Werkzeuge (&T)"
54
 
55
@@ -362,6 +378,14 @@
56
 Basic.Settings.Output.Mode.Simple="Einfach"
57
 Basic.Settings.Output.Mode.Adv="Erweitert"
58
 Basic.Settings.Output.Mode.FFmpeg="FFmpeg Ausgabe"
59
+Basic.Settings.Output.UseReplayBuffer="Replaypuffer aktivieren"
60
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Maximale Replayzeit (Sekunden)"
61
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Maximale Speichernutzung (RAM) in Megabyte"
62
+Basic.Settings.Output.ReplayBuffer.Estimate="Geschätzte Speichernutzung (RAM): %1 MB"
63
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Speichernutzung kann nicht geschätzt werden.  Stellen Sie bitte die maximale Speichergrenze ein."
64
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Hinweis: Achten Sie darauf, einen Hotkey für den Replaypuffer im Abschnitt Hotkeys festzulegen)"
65
+Basic.Settings.Output.ReplayBuffer.Prefix="Replaypuffer Dateiname Prefix"
66
+Basic.Settings.Output.ReplayBuffer.Suffix="Suffix"
67
 Basic.Settings.Output.Simple.SavePath="Aufnahmepfad"
68
 Basic.Settings.Output.Simple.RecordingQuality="Aufnahmequalität"
69
 Basic.Settings.Output.Simple.RecordingQuality.Stream="Gleiche wie Stream"
70
@@ -399,6 +423,8 @@
71
 Basic.Settings.Output.Adv.Audio.Track2="Spur 2"
72
 Basic.Settings.Output.Adv.Audio.Track3="Spur 3"
73
 Basic.Settings.Output.Adv.Audio.Track4="Spur 4"
74
+Basic.Settings.Output.Adv.Audio.Track5="Spur 5"
75
+Basic.Settings.Output.Adv.Audio.Track6="Spur 6"
76
 
77
 Basic.Settings.Output.Adv.Recording="Aufnehmen"
78
 Basic.Settings.Output.Adv.Recording.Type="Art"
79
@@ -497,10 +523,6 @@
80
 Basic.Settings.Hotkeys="Hotkeys"
81
 Basic.Settings.Hotkeys.Pair="Mit '%1' geteilte Tastenkombinationen funktionieren als Schalter"
82
 
83
-Basic.Hotkeys.StartStreaming="Streaming starten"
84
-Basic.Hotkeys.StopStreaming="Streaming stoppen"
85
-Basic.Hotkeys.StartRecording="Aufnahme starten"
86
-Basic.Hotkeys.StopRecording="Aufnahme stoppen"
87
 Basic.Hotkeys.SelectScene="Zu Szene wechseln"
88
 
89
 Basic.SystemTray.Show="Anzeigen"
90
obs-studio-0.16.6.tar.xz/UI/data/locale/el-GR.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/el-GR.ini Changed
12
 
1
@@ -361,10 +361,6 @@
2
 Basic.AdvAudio.AudioTracks="Κομμάτια"
3
 
4
 
5
-Basic.Hotkeys.StartStreaming="Έναρξη Μετάδοσης"
6
-Basic.Hotkeys.StopStreaming="Διακοπή Μετάδοσης"
7
-Basic.Hotkeys.StartRecording="Έναρξη Καταγραφής"
8
-Basic.Hotkeys.StopRecording="Διακοπή Καταγραφής"
9
 Basic.Hotkeys.SelectScene="Μετάβαση σε σκηνή"
10
 
11
 
12
obs-studio-0.16.6.tar.xz/UI/data/locale/en-US.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/en-US.ini Changed
90
 
1
@@ -58,6 +58,9 @@
2
 Minutes="Minutes"
3
 Seconds="Seconds"
4
 Deprecated="Deprecated"
5
+ReplayBuffer="Replay Buffer"
6
+Import="Import"
7
+Export="Export"
8
 
9
 # quick transitions
10
 QuickTransitions.SwapScenes="Swap Preview/Output Scenes After Transitioning"
11
@@ -123,6 +126,8 @@
12
 Output.RecordNoSpace.Msg="There is not sufficient disk space to continue recording."
13
 Output.RecordError.Title="Recording error"
14
 Output.RecordError.Msg="An unspecified error occurred while recording."
15
+Output.ReplayBuffer.NoHotkey.Title="No hotkey set!"
16
+Output.ReplayBuffer.NoHotkey.Msg="No save hotkey set for replay buffer.  Please set the \"Save\" hotkey to use for saving replay recordings."
17
 
18
 # output recording messages
19
 Output.BadPath.Title="Bad File Path"
20
@@ -304,9 +309,12 @@
21
 Basic.Main.Sources="Sources"
22
 Basic.Main.Connecting="Connecting..."
23
 Basic.Main.StartRecording="Start Recording"
24
+Basic.Main.StartReplayBuffer="Start Replay Buffer"
25
 Basic.Main.StartStreaming="Start Streaming"
26
 Basic.Main.StopRecording="Stop Recording"
27
 Basic.Main.StoppingRecording="Stopping Recording..."
28
+Basic.Main.StopReplayBuffer="Stop Replay Buffer"
29
+Basic.Main.StoppingReplayBuffer="Stopping Replay Buffer..."
30
 Basic.Main.StopStreaming="Stop Streaming"
31
 Basic.Main.StoppingStreaming="Stopping Stream..."
32
 Basic.Main.ForceStopStreaming="Stop Streaming (discard delay)"
33
@@ -336,6 +344,8 @@
34
 Basic.MainMenu.Edit.Scale.Output="Output (%1x%2)"
35
 Basic.MainMenu.Edit.Transform="&Transform"
36
 Basic.MainMenu.Edit.Transform.EditTransform="&Edit Transform..."
37
+Basic.MainMenu.Edit.Transform.CopyTransform="Copy Transform"
38
+Basic.MainMenu.Edit.Transform.PasteTransform="Paste Transform"
39
 Basic.MainMenu.Edit.Transform.ResetTransform="&Reset Transform"
40
 Basic.MainMenu.Edit.Transform.Rotate90CW="Rotate 90 degrees CW"
41
 Basic.MainMenu.Edit.Transform.Rotate90CCW="Rotate 90 degrees CCW"
42
@@ -362,6 +372,12 @@
43
 # basic mode profile/scene collection menus
44
 Basic.MainMenu.SceneCollection="&Scene Collection"
45
 Basic.MainMenu.Profile="&Profile"
46
+Basic.MainMenu.Profile.Import="Import Profile"
47
+Basic.MainMenu.Profile.Export="Export Profile"
48
+Basic.MainMenu.SceneCollection.Import="Import Scene Collection"
49
+Basic.MainMenu.SceneCollection.Export="Export Scene Collection"
50
+Basic.MainMenu.Profile.Exists="The profile already exists"
51
+Basic.MainMenu.SceneCollection.Exists="The scene collection already exists"
52
 
53
 # basic mode help menu
54
 Basic.MainMenu.Tools="&Tools"
55
@@ -414,6 +430,14 @@
56
 Basic.Settings.Output.Mode.Simple="Simple"
57
 Basic.Settings.Output.Mode.Adv="Advanced"
58
 Basic.Settings.Output.Mode.FFmpeg="FFmpeg Output"
59
+Basic.Settings.Output.UseReplayBuffer="Enable Replay Buffer"
60
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Maximum Replay Time (Seconds)"
61
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Maximum Memory (Megabytes)"
62
+Basic.Settings.Output.ReplayBuffer.Estimate="Estimated memory usage: %1 MB"
63
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Cannot estimate memory usage.  Please set maximum memory limit."
64
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Note: Make sure to set a hotkey for the replay buffer in the hotkeys section)"
65
+Basic.Settings.Output.ReplayBuffer.Prefix="Replay Buffer Filename Prefix"
66
+Basic.Settings.Output.ReplayBuffer.Suffix="Suffix"
67
 Basic.Settings.Output.Simple.SavePath="Recording Path"
68
 Basic.Settings.Output.Simple.RecordingQuality="Recording Quality"
69
 Basic.Settings.Output.Simple.RecordingQuality.Stream="Same as stream"
70
@@ -452,6 +476,8 @@
71
 Basic.Settings.Output.Adv.Audio.Track2="Track 2"
72
 Basic.Settings.Output.Adv.Audio.Track3="Track 3"
73
 Basic.Settings.Output.Adv.Audio.Track4="Track 4"
74
+Basic.Settings.Output.Adv.Audio.Track5="Track 5"
75
+Basic.Settings.Output.Adv.Audio.Track6="Track 6"
76
 
77
 # basic mode 'output' settings - advanced section - recording subsection
78
 Basic.Settings.Output.Adv.Recording="Recording"
79
@@ -560,10 +586,6 @@
80
 Basic.Settings.Hotkeys.Pair="Key combinations shared with '%1' act as toggles"
81
 
82
 # basic mode hotkeys
83
-Basic.Hotkeys.StartStreaming="Start Streaming"
84
-Basic.Hotkeys.StopStreaming="Stop Streaming"
85
-Basic.Hotkeys.StartRecording="Start Recording"
86
-Basic.Hotkeys.StopRecording="Stop Recording"
87
 Basic.Hotkeys.SelectScene="Switch to scene"
88
 
89
 # system tray
90
obs-studio-0.16.6.tar.xz/UI/data/locale/es-ES.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/es-ES.ini Changed
90
 
1
@@ -53,6 +53,9 @@
2
 Minutes="Minutos"
3
 Seconds="Segundos"
4
 Deprecated="Obsoleto"
5
+ReplayBuffer="Búfer de reproducción"
6
+Import="Importar"
7
+Export="Exportar"
8
 
9
 QuickTransitions.SwapScenes="Cambiar vista previa y salida escenas después de la transición"
10
 QuickTransitions.SwapScenesTT="Cambia la vista previa y salida escenas después de la transición (si todavía existe la escena original de la salida). \nEsto no deshará cualquier cambio que pueda haber hecho a la escena original de la salida."
11
@@ -107,6 +110,8 @@
12
 Output.RecordNoSpace.Msg="No hay suficiente espacio en disco para continuar grabando."
13
 Output.RecordError.Title="Error en la grabación"
14
 Output.RecordError.Msg="Se ha producido un error no especificado durante la grabación."
15
+Output.ReplayBuffer.NoHotkey.Title="¡Sin tecla de acceso rápido!"
16
+Output.ReplayBuffer.NoHotkey.Msg="Sin tecla de acceso rápido establecida para el búfer de reproducción. Configure la tecla de acceso \"Guardar\" para guardar las grabaciones de reproducción."
17
 
18
 Output.BadPath.Title="Ruta de archivo incorrecta"
19
 Output.BadPath.Text="La ruta de salida de archivos establecida no es válida.  Por favor, compruebe su configuración para confirmar que se ha establecido una ruta de archivos válida."
20
@@ -262,9 +267,12 @@
21
 Basic.Main.Sources="Fuentes"
22
 Basic.Main.Connecting="Conectando..."
23
 Basic.Main.StartRecording="Iniciar grabación"
24
+Basic.Main.StartReplayBuffer="Iniciar la reproducción del búfer"
25
 Basic.Main.StartStreaming="Iniciar Transmisión"
26
 Basic.Main.StopRecording="Detener grabación"
27
 Basic.Main.StoppingRecording="Deteniendo la grabación..."
28
+Basic.Main.StopReplayBuffer="Detener la reproducción del búfer"
29
+Basic.Main.StoppingReplayBuffer="Deteniendo la reproducción del búfer..."
30
 Basic.Main.StopStreaming="Detener Transmisión"
31
 Basic.Main.StoppingStreaming="Deteniendo la trasmisión..."
32
 Basic.Main.ForceStopStreaming="Parar Transmisión (descartar retraso)"
33
@@ -292,6 +300,8 @@
34
 Basic.MainMenu.Edit.Scale.Output="Salida (%1x%2)"
35
 Basic.MainMenu.Edit.Transform="&Transformar"
36
 Basic.MainMenu.Edit.Transform.EditTransform="&Editar Transformación..."
37
+Basic.MainMenu.Edit.Transform.CopyTransform="Copiar transformación"
38
+Basic.MainMenu.Edit.Transform.PasteTransform="Pegar trasformación"
39
 Basic.MainMenu.Edit.Transform.ResetTransform="&Restablecer transformación"
40
 Basic.MainMenu.Edit.Transform.Rotate90CW="Girar 90 grados en el sentido de las agujas del reloj"
41
 Basic.MainMenu.Edit.Transform.Rotate90CCW="Girar 90 grados contra el sentido de las agujas del reloj"
42
@@ -316,6 +326,12 @@
43
 
44
 Basic.MainMenu.SceneCollection="&Colección de Escenas"
45
 Basic.MainMenu.Profile="&Perfil"
46
+Basic.MainMenu.Profile.Import="Importar perfil"
47
+Basic.MainMenu.Profile.Export="Exportar perfil"
48
+Basic.MainMenu.SceneCollection.Import="Importar colección de escenas"
49
+Basic.MainMenu.SceneCollection.Export="Exportar colección de escenas"
50
+Basic.MainMenu.Profile.Exists="El perfil ya existe"
51
+Basic.MainMenu.SceneCollection.Exists="La colección de escenas ya existe"
52
 
53
 Basic.MainMenu.Tools="&Herramientas"
54
 
55
@@ -362,6 +378,14 @@
56
 Basic.Settings.Output.Mode.Simple="Sencillo"
57
 Basic.Settings.Output.Mode.Adv="Avanzado"
58
 Basic.Settings.Output.Mode.FFmpeg="Salida de FFmpeg"
59
+Basic.Settings.Output.UseReplayBuffer="Activar la reproducción del búfer"
60
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Tiempo de reproducción máximo (segundos)"
61
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Memoria máxima (MB)"
62
+Basic.Settings.Output.ReplayBuffer.Estimate="Uso estimado de memoria: %1 MB"
63
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="No se puede estimar el uso de memoria. Establezca el límite máximo de memoria."
64
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Nota: Asegúrese de establecer una tecla de acceso rápido para el búfer de reproducción en la sección de teclas rápidas)"
65
+Basic.Settings.Output.ReplayBuffer.Prefix="Prefijo del nombre de archivo del búfer"
66
+Basic.Settings.Output.ReplayBuffer.Suffix="Sufijo"
67
 Basic.Settings.Output.Simple.SavePath="Ruta de grabación"
68
 Basic.Settings.Output.Simple.RecordingQuality="Calidad de grabación"
69
 Basic.Settings.Output.Simple.RecordingQuality.Stream="Igual a la emision"
70
@@ -399,6 +423,8 @@
71
 Basic.Settings.Output.Adv.Audio.Track2="Pista 2"
72
 Basic.Settings.Output.Adv.Audio.Track3="Pista 3"
73
 Basic.Settings.Output.Adv.Audio.Track4="Pista 4"
74
+Basic.Settings.Output.Adv.Audio.Track5="Pista 5"
75
+Basic.Settings.Output.Adv.Audio.Track6="Pista 6"
76
 
77
 Basic.Settings.Output.Adv.Recording="Grabando"
78
 Basic.Settings.Output.Adv.Recording.Type="Tipo"
79
@@ -497,10 +523,6 @@
80
 Basic.Settings.Hotkeys="Atajos"
81
 Basic.Settings.Hotkeys.Pair="Combinaciones de teclas con '%1' actúan como interruptores"
82
 
83
-Basic.Hotkeys.StartStreaming="Iniciar Transmisión"
84
-Basic.Hotkeys.StopStreaming="Detener Transmisión"
85
-Basic.Hotkeys.StartRecording="Iniciar grabación"
86
-Basic.Hotkeys.StopRecording="Detener grabación"
87
 Basic.Hotkeys.SelectScene="Cambiar a la escena"
88
 
89
 Basic.SystemTray.Show="Mostrar"
90
obs-studio-0.16.6.tar.xz/UI/data/locale/eu-ES.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/eu-ES.ini Changed
90
 
1
@@ -53,6 +53,9 @@
2
 Minutes="minutu"
3
 Seconds="segundo"
4
 Deprecated="Zaharkitua"
5
+ReplayBuffer="Erreprodukzio bufferra"
6
+Import="Inportatu"
7
+Export="Esportatu"
8
 
9
 QuickTransitions.SwapScenes="Trukatu Aurrebista/Irteera-eszenak trantsizioen ondoren"
10
 QuickTransitions.SwapScenesTT="Trukatu aurrebistak eta irteera-eszenak trantsizioen ondoren (baldin eta irteerakoaren jatorrizkoa eszena badago).\n Honek ez du desegingo irteerakoaren jatorrizko eszenari egindako aldaketak."
11
@@ -107,6 +110,8 @@
12
 Output.RecordNoSpace.Msg="Ez dago nahikoa tokirik diskoan grabatzen jarraitzeko."
13
 Output.RecordError.Title="Grabazio akatsa"
14
 Output.RecordError.Msg="Zehaztugabeko akats bat gertatu da grabatzerakoan."
15
+Output.ReplayBuffer.NoHotkey.Title="Laster tekla ezarri gabe!"
16
+Output.ReplayBuffer.NoHotkey.Msg="Ez da ezarri gordetzeko laster teklarik erreprodukzio bufferrerako. Ezarri \"Gorde\" laster tekla  erreprodukzio bufferrak gordetzeko."
17
 
18
 Output.BadPath.Title="Fitxategi-bide okerra"
19
 Output.BadPath.Text="Ezarritako fitxategiaren irteera-bidea baliogabea da. Egiaztatu zure ezarpenak baieztatzeko baliozko fitxategi-bidea ezarri dela."
20
@@ -262,9 +267,12 @@
21
 Basic.Main.Sources="Iturburuak"
22
 Basic.Main.Connecting="Konektatzen..."
23
 Basic.Main.StartRecording="Hasi grabazioa"
24
+Basic.Main.StartReplayBuffer="Abiatu erreprodukzio bufferra"
25
 Basic.Main.StartStreaming="Hasi transmisioa"
26
 Basic.Main.StopRecording="Gelditu grabazioa"
27
 Basic.Main.StoppingRecording="Grabazioa gelditzen..."
28
+Basic.Main.StopReplayBuffer="Gelditu erreprodukzio buferra"
29
+Basic.Main.StoppingReplayBuffer="Erreprodukzio bufferra gelditzen..."
30
 Basic.Main.StopStreaming="Gelditu transmisioa"
31
 Basic.Main.StoppingStreaming="Transmisioa gelditzen..."
32
 Basic.Main.ForceStopStreaming="Gelditu transmisioa (baztertu atzerapena)"
33
@@ -292,6 +300,8 @@
34
 Basic.MainMenu.Edit.Scale.Output="Irteera (%1x%2)"
35
 Basic.MainMenu.Edit.Transform="&Eraldatu"
36
 Basic.MainMenu.Edit.Transform.EditTransform="E&ditatu eraldaketa..."
37
+Basic.MainMenu.Edit.Transform.CopyTransform="Kopiatu eraldaketa"
38
+Basic.MainMenu.Edit.Transform.PasteTransform="Itsatsi eraldaketa"
39
 Basic.MainMenu.Edit.Transform.ResetTransform="&Berrezarri eraldaketa"
40
 Basic.MainMenu.Edit.Transform.Rotate90CW="Biratu 90 gradu erlojuaren norabidean"
41
 Basic.MainMenu.Edit.Transform.Rotate90CCW="Biratu 90 gradu erlojuaren kontrako norabidean"
42
@@ -316,6 +326,12 @@
43
 
44
 Basic.MainMenu.SceneCollection="&Eszena-bilduma"
45
 Basic.MainMenu.Profile="&Profila"
46
+Basic.MainMenu.Profile.Import="Inportatu profila"
47
+Basic.MainMenu.Profile.Export="Esportatu profila"
48
+Basic.MainMenu.SceneCollection.Import="Inportatu eszena bilduma"
49
+Basic.MainMenu.SceneCollection.Export="Esportatu eszena bilduma"
50
+Basic.MainMenu.Profile.Exists="Profila lehendik ere badago"
51
+Basic.MainMenu.SceneCollection.Exists="Eszena bilduma lehendik ere badago"
52
 
53
 Basic.MainMenu.Tools="&Tresnak"
54
 
55
@@ -362,6 +378,14 @@
56
 Basic.Settings.Output.Mode.Simple="Arrunta"
57
 Basic.Settings.Output.Mode.Adv="Aurreratua"
58
 Basic.Settings.Output.Mode.FFmpeg="FFmpeg Irteera"
59
+Basic.Settings.Output.UseReplayBuffer="Gaitu erreprodukzio bufferra"
60
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Erreprodukzioaren gehienezko denbora (segundotan)"
61
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Gehienezko memoria (megabytetan)"
62
+Basic.Settings.Output.ReplayBuffer.Estimate="Ustezko memoria erabilera: %1 MB"
63
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Ezin da kalkulatu memoria erabilera. Ezarri gehienezko memoria."
64
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Oharra: Aseguratu bufferraren erreprodukziorako laster tekla bat ezarri duzula laster teklen atalean)"
65
+Basic.Settings.Output.ReplayBuffer.Prefix="Erreprodukzio bufferraren fitxategi aurrizkia"
66
+Basic.Settings.Output.ReplayBuffer.Suffix="Atzizkia"
67
 Basic.Settings.Output.Simple.SavePath="Grabazio-bidea"
68
 Basic.Settings.Output.Simple.RecordingQuality="Grabazio-kalitatea"
69
 Basic.Settings.Output.Simple.RecordingQuality.Stream="Transmisioaren berdina"
70
@@ -399,6 +423,8 @@
71
 Basic.Settings.Output.Adv.Audio.Track2="2 pista"
72
 Basic.Settings.Output.Adv.Audio.Track3="3 pista"
73
 Basic.Settings.Output.Adv.Audio.Track4="4 pista"
74
+Basic.Settings.Output.Adv.Audio.Track5="5. pista"
75
+Basic.Settings.Output.Adv.Audio.Track6="6. pista"
76
 
77
 Basic.Settings.Output.Adv.Recording="Grabatzen"
78
 Basic.Settings.Output.Adv.Recording.Type="Mota"
79
@@ -497,10 +523,6 @@
80
 Basic.Settings.Hotkeys="Laster-teklak"
81
 Basic.Settings.Hotkeys.Pair="'%1'-rekin egindako tekla konbinazioek txandakatze moduan jokatzen dute"
82
 
83
-Basic.Hotkeys.StartStreaming="Hasi transmisioa"
84
-Basic.Hotkeys.StopStreaming="Gelditu transmisioa"
85
-Basic.Hotkeys.StartRecording="Hasi Grabazioa"
86
-Basic.Hotkeys.StopRecording="Gelditu grabazioa"
87
 Basic.Hotkeys.SelectScene="Aldatu eszenara"
88
 
89
 Basic.SystemTray.Show="Erakutsi"
90
obs-studio-0.16.6.tar.xz/UI/data/locale/fi-FI.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/fi-FI.ini Changed
81
 
1
@@ -53,6 +53,9 @@
2
 Minutes="Minuuttia"
3
 Seconds="Sekuntia"
4
 Deprecated="Vanhentunut"
5
+ReplayBuffer="Toistopuskuri"
6
+Import="Tuo"
7
+Export="Vie"
8
 
9
 QuickTransitions.SwapScenes="Vaihda esikatselu- ja ulostulo-skenet siirtymän jälkeen"
10
 QuickTransitions.SwapScenesTT="Vaihda esikatselu- ja ulostulo-skenet siirtymän jälkeen (jos ulostulon alkuperäinen skene on yhä olemassa).\nTämä ei peruuta muutoksia joita on tehty alkuperäiseen skeneen."
11
@@ -107,6 +110,8 @@
12
 Output.RecordNoSpace.Msg="Levytilaa ei ole riittävästi tallennuksen jatkamiseen."
13
 Output.RecordError.Title="Tallennusvirhe"
14
 Output.RecordError.Msg="Tallennuksen aikana tapahtui määrittelemätön virhe."
15
+Output.ReplayBuffer.NoHotkey.Title="Pikanäppäintä ei ole asetettu!"
16
+Output.ReplayBuffer.NoHotkey.Msg="Tallennuksen pikanäppäintä ei ole asetettu toistopuskurille. Aseta \"Tallenna\"-pikanäppäin tallentaaksesi uusinnat."
17
 
18
 Output.BadPath.Title="Viallinen tiedostopolku"
19
 Output.BadPath.Text="Asetettu tiedostopolku on viallinen.  Tarkista asetuksistasi, että tiedostopolku on asetettu oikein."
20
@@ -262,9 +267,12 @@
21
 Basic.Main.Sources="Lähteet"
22
 Basic.Main.Connecting="Yhdistetään..."
23
 Basic.Main.StartRecording="Aloita tallennus"
24
+Basic.Main.StartReplayBuffer="Käynnistä toistopuskuri"
25
 Basic.Main.StartStreaming="Aloita lähetys"
26
 Basic.Main.StopRecording="Pysäytä tallennus"
27
 Basic.Main.StoppingRecording="Pysäytetään tallennusta..."
28
+Basic.Main.StopReplayBuffer="Pysäytä toistopuskuri"
29
+Basic.Main.StoppingReplayBuffer="Pysäytetään toistopuskuri..."
30
 Basic.Main.StopStreaming="Pysäytä lähetys"
31
 Basic.Main.StoppingStreaming="Pysäytetään lähetystä..."
32
 Basic.Main.ForceStopStreaming="Lopeta lähetys (ohita viive)"
33
@@ -292,6 +300,8 @@
34
 Basic.MainMenu.Edit.Scale.Output="Ulostulo (%1x%2)"
35
 Basic.MainMenu.Edit.Transform="Muu&nna"
36
 Basic.MainMenu.Edit.Transform.EditTransform="M&uokkaa muunnosta..."
37
+Basic.MainMenu.Edit.Transform.CopyTransform="Kopioi muunnos"
38
+Basic.MainMenu.Edit.Transform.PasteTransform="Liitä muunnos"
39
 Basic.MainMenu.Edit.Transform.ResetTransform="&Nollaa muunnos"
40
 Basic.MainMenu.Edit.Transform.Rotate90CW="Kierrä 90 astetta myötäpäivään"
41
 Basic.MainMenu.Edit.Transform.Rotate90CCW="Kierrä 90 astetta vastapäivään"
42
@@ -316,6 +326,12 @@
43
 
44
 Basic.MainMenu.SceneCollection="&Skene-kokoelma"
45
 Basic.MainMenu.Profile="&Profiili"
46
+Basic.MainMenu.Profile.Import="Tuo profiili"
47
+Basic.MainMenu.Profile.Export="Vie profiili"
48
+Basic.MainMenu.SceneCollection.Import="Tuo skene-kokoelma"
49
+Basic.MainMenu.SceneCollection.Export="Vie skene-kokoelma"
50
+Basic.MainMenu.Profile.Exists="Profiili on jo olemassa"
51
+Basic.MainMenu.SceneCollection.Exists="Skene-kokoelma on jo olemassa"
52
 
53
 Basic.MainMenu.Tools="T&yökalut"
54
 
55
@@ -362,6 +378,14 @@
56
 Basic.Settings.Output.Mode.Simple="Yksinkertainen"
57
 Basic.Settings.Output.Mode.Adv="Kehittynyt"
58
 Basic.Settings.Output.Mode.FFmpeg="FFmpeg ulostulo"
59
+Basic.Settings.Output.UseReplayBuffer="Ota toistopuskuri käyttöön"
60
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Uusinnan pisin aika (Sekunteina)"
61
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Muistiraja (Megatavuja)"
62
+Basic.Settings.Output.ReplayBuffer.Estimate="Arvioitu muistinkäyttö: %1 MB"
63
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Muistin käyttöä ei voida arvioida.  Valitse muistiraja."
64
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Huomio: Varmista että toistopuskurin pikanäppäin on asetettuna asetuksista)"
65
+Basic.Settings.Output.ReplayBuffer.Prefix="Toistopuskurin tiedostonimen etuliite"
66
+Basic.Settings.Output.ReplayBuffer.Suffix="Pääte"
67
 Basic.Settings.Output.Simple.SavePath="Tallennuksen polku"
68
 Basic.Settings.Output.Simple.RecordingQuality="Tallennuksen laatu"
69
 Basic.Settings.Output.Simple.RecordingQuality.Stream="Sama kuin lähetyksessä"
70
@@ -497,10 +521,6 @@
71
 Basic.Settings.Hotkeys="Pikanäppäimet"
72
 Basic.Settings.Hotkeys.Pair="Yhteiset näppäinyhdistelmät '%1':n kanssa toimivat 'togglena'"
73
 
74
-Basic.Hotkeys.StartStreaming="Aloita lähetys"
75
-Basic.Hotkeys.StopStreaming="Pysäytä lähetys"
76
-Basic.Hotkeys.StartRecording="Aloita tallennus"
77
-Basic.Hotkeys.StopRecording="Pysäytä tallennus"
78
 Basic.Hotkeys.SelectScene="Vaihda skeneen"
79
 
80
 Basic.SystemTray.Show="Näytä"
81
obs-studio-0.16.6.tar.xz/UI/data/locale/fr-FR.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/fr-FR.ini Changed
90
 
1
@@ -53,6 +53,9 @@
2
 Minutes="Minutes"
3
 Seconds="Secondes"
4
 Deprecated="Obsolète"
5
+ReplayBuffer="Tampon de relecture"
6
+Import="Importer"
7
+Export="Exporter"
8
 
9
 QuickTransitions.SwapScenes="Permuter les scènes d'aperçu et de sortie après la transition"
10
 QuickTransitions.SwapScenesTT="Permute les scènes d'aperçu et de sortie après la transition (si la scène d'origine de la sortie existe toujours). \nCela n'annulera pas les modifications qui auront pu être faites sur la scène d'origine de la sortie."
11
@@ -107,6 +110,8 @@
12
 Output.RecordNoSpace.Msg="Il n'y a pas suffisamment d'espace disque pour continuer l'enregistrement."
13
 Output.RecordError.Title="Erreur d'enregistrement"
14
 Output.RecordError.Msg="Une erreur non spécifiée s'est produite lors de l'enregistrement."
15
+Output.ReplayBuffer.NoHotkey.Title="Aucun raccourci clavier défini !"
16
+Output.ReplayBuffer.NoHotkey.Msg="Aucun raccourci clavier défini pour le tampon de relecture. Veuillez en définir un pour utiliser cette fonction."
17
 
18
 Output.BadPath.Title="Chemin d'accès au fichier incorrect"
19
 Output.BadPath.Text="Le chemin configuré pour le flux sortant est invalide. Veuillez vérifier vos paramètres pour confirmer la présence d'un chemin valide."
20
@@ -262,9 +267,12 @@
21
 Basic.Main.Sources="Sources"
22
 Basic.Main.Connecting="Connexion en cours..."
23
 Basic.Main.StartRecording="Démarrer l'enregistrement"
24
+Basic.Main.StartReplayBuffer="Démarrer le tampon de relecture"
25
 Basic.Main.StartStreaming="Commencer le streaming"
26
 Basic.Main.StopRecording="Arrêter l'enregistrement"
27
 Basic.Main.StoppingRecording="Arrêt de l'enregistrement..."
28
+Basic.Main.StopReplayBuffer="Arrêter le tampon de relecture"
29
+Basic.Main.StoppingReplayBuffer="Arrêt du tampon de relecture..."
30
 Basic.Main.StopStreaming="Arrêter le streaming"
31
 Basic.Main.StoppingStreaming="Arrêt du stream..."
32
 Basic.Main.ForceStopStreaming="Arrêter le streaming (annule le retard)"
33
@@ -292,6 +300,8 @@
34
 Basic.MainMenu.Edit.Scale.Output="Sortie (%1x%2)"
35
 Basic.MainMenu.Edit.Transform="&Transformer"
36
 Basic.MainMenu.Edit.Transform.EditTransform="Éditer la transformation..."
37
+Basic.MainMenu.Edit.Transform.CopyTransform="Copier la transformation"
38
+Basic.MainMenu.Edit.Transform.PasteTransform="Coller la transformation"
39
 Basic.MainMenu.Edit.Transform.ResetTransform="Réinitialiser la transformation"
40
 Basic.MainMenu.Edit.Transform.Rotate90CW="Rotation de 90° sens horaire"
41
 Basic.MainMenu.Edit.Transform.Rotate90CCW="Rotation de 90° sens antihoraire"
42
@@ -316,6 +326,12 @@
43
 
44
 Basic.MainMenu.SceneCollection="Collection de &scènes"
45
 Basic.MainMenu.Profile="&Profil"
46
+Basic.MainMenu.Profile.Import="Importer un profil"
47
+Basic.MainMenu.Profile.Export="Exporter un profil"
48
+Basic.MainMenu.SceneCollection.Import="Importer une collection de scènes"
49
+Basic.MainMenu.SceneCollection.Export="Exporter une collection de scènes"
50
+Basic.MainMenu.Profile.Exists="Ce profil existe déjà"
51
+Basic.MainMenu.SceneCollection.Exists="Cette collection de scène existe déjà"
52
 
53
 Basic.MainMenu.Tools="Outils"
54
 
55
@@ -362,6 +378,14 @@
56
 Basic.Settings.Output.Mode.Simple="Simple"
57
 Basic.Settings.Output.Mode.Adv="Avancé"
58
 Basic.Settings.Output.Mode.FFmpeg="Sortie FFmpeg"
59
+Basic.Settings.Output.UseReplayBuffer="Activer le tampon de relecture"
60
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Temps de relecture maximal (secondes)"
61
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Mémoire maximum (mégaoctets)"
62
+Basic.Settings.Output.ReplayBuffer.Estimate="Estimation de la mémoire utilisée : %1 Mo"
63
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Impossible d'estimer l'utilisation de la mémoire. Veuillez définir une limite de mémoire maximale."
64
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Remarque : veillez à définir un raccourci clavier pour le tampon de relecture dans la section des raccourcis clavier)"
65
+Basic.Settings.Output.ReplayBuffer.Prefix="Nom du fichier du tampon commençant par"
66
+Basic.Settings.Output.ReplayBuffer.Suffix="Finissant par"
67
 Basic.Settings.Output.Simple.SavePath="Chemin d'accès de l'enregistrement"
68
 Basic.Settings.Output.Simple.RecordingQuality="Qualité d'enregistrement"
69
 Basic.Settings.Output.Simple.RecordingQuality.Stream="Identique au stream"
70
@@ -399,6 +423,8 @@
71
 Basic.Settings.Output.Adv.Audio.Track2="Piste 2"
72
 Basic.Settings.Output.Adv.Audio.Track3="Piste 3"
73
 Basic.Settings.Output.Adv.Audio.Track4="Piste 4"
74
+Basic.Settings.Output.Adv.Audio.Track5="Piste 5"
75
+Basic.Settings.Output.Adv.Audio.Track6="Piste 6"
76
 
77
 Basic.Settings.Output.Adv.Recording="Enregistrement"
78
 Basic.Settings.Output.Adv.Recording.Type="Type "
79
@@ -497,10 +523,6 @@
80
 Basic.Settings.Hotkeys="Raccourcis clavier"
81
 Basic.Settings.Hotkeys.Pair="Les combinaisons de touches partagées avec '%1' agissent comme déclancheur"
82
 
83
-Basic.Hotkeys.StartStreaming="Commencer le streaming"
84
-Basic.Hotkeys.StopStreaming="Arrêter le streaming"
85
-Basic.Hotkeys.StartRecording="Démarrer l'enregistrement"
86
-Basic.Hotkeys.StopRecording="Arrêter l'enregistrement"
87
 Basic.Hotkeys.SelectScene="Passer à la scène"
88
 
89
 Basic.SystemTray.Show="Restaurer"
90
obs-studio-0.16.6.tar.xz/UI/data/locale/gl-ES.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/gl-ES.ini Changed
12
 
1
@@ -362,10 +362,6 @@
2
 Basic.AdvAudio.AudioTracks="Pistas"
3
 
4
 
5
-Basic.Hotkeys.StartStreaming="Iniciar retransmisión"
6
-Basic.Hotkeys.StopStreaming="Deter retransmisión"
7
-Basic.Hotkeys.StartRecording="Iniciar gravación"
8
-Basic.Hotkeys.StopRecording="Deter gravación"
9
 
10
 
11
 
12
obs-studio-0.16.6.tar.xz/UI/data/locale/he-IL.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/he-IL.ini Changed
12
 
1
@@ -483,10 +483,6 @@
2
 Basic.Settings.Hotkeys="מקשי קיצור"
3
 Basic.Settings.Hotkeys.Pair="צירופי מקשים משותים עם '%1' משמשים כמחליפים"
4
 
5
-Basic.Hotkeys.StartStreaming="התחל הזרמת נתונים"
6
-Basic.Hotkeys.StopStreaming="עצור הזרמת נתונים"
7
-Basic.Hotkeys.StartRecording="התחל הקלטה"
8
-Basic.Hotkeys.StopRecording="עצור הקלטה"
9
 Basic.Hotkeys.SelectScene="עבור לסצנה"
10
 
11
 Basic.SystemTray.Show="הצג"
12
obs-studio-0.16.6.tar.xz/UI/data/locale/hr-HR.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/hr-HR.ini Changed
31
 
1
@@ -52,6 +52,7 @@
2
 Hours="Sati"
3
 Minutes="Minuta"
4
 Seconds="Sekundi"
5
+Deprecated="Prevaziđeno"
6
 
7
 QuickTransitions.SwapScenes="Zameni scene pregleda/izlaza nakon prelaza"
8
 QuickTransitions.SwapScenesTT="Zamenjuje scene pregleda i izlaza nakon prelaza (ako originalna scena izlaza još uvek postoji).\nOvo neće poništiti promene koje su načinjene nad originalnom scenom izlaza."
9
@@ -285,6 +286,10 @@
10
 Basic.MainMenu.Edit.UndoAction="Vrati $1 (&U)"
11
 Basic.MainMenu.Edit.RedoAction="U&radi ponovo $1"
12
 Basic.MainMenu.Edit.LockPreview="Zak&ljučaj prikaz"
13
+Basic.MainMenu.Edit.Scale="Pregled &skaliranja"
14
+Basic.MainMenu.Edit.Scale.Window="Skaliraj na veličinu prozora"
15
+Basic.MainMenu.Edit.Scale.Canvas="Platno (%1x%2)"
16
+Basic.MainMenu.Edit.Scale.Output="Izlaz (%1x%2)"
17
 Basic.MainMenu.Edit.Transform="&Transformiši"
18
 Basic.MainMenu.Edit.Transform.EditTransform="Izm&eni transformaciju..."
19
 Basic.MainMenu.Edit.Transform.ResetTransform="Poništi t&ransformaciju"
20
@@ -492,10 +497,6 @@
21
 Basic.Settings.Hotkeys="Prečice"
22
 Basic.Settings.Hotkeys.Pair="Kombinacije tastera deljene sa '%1' se ponašaju kao prekidači"
23
 
24
-Basic.Hotkeys.StartStreaming="Započni strimovanje"
25
-Basic.Hotkeys.StopStreaming="Zaustavi strimovanje"
26
-Basic.Hotkeys.StartRecording="Počni snimanje"
27
-Basic.Hotkeys.StopRecording="Zaustavi snimanje"
28
 Basic.Hotkeys.SelectScene="Prebaci na scenu"
29
 
30
 Basic.SystemTray.Show="Prikaži"
31
obs-studio-0.16.6.tar.xz/UI/data/locale/hu-HU.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/hu-HU.ini Changed
90
 
1
@@ -53,6 +53,9 @@
2
 Minutes="Perc"
3
 Seconds="Másodperc"
4
 Deprecated="Elavult"
5
+ReplayBuffer="Visszajátszás puffer"
6
+Import="Importálás"
7
+Export="Exportálás"
8
 
9
 QuickTransitions.SwapScenes="Előnézeti/Kimeneti Jelenetek cseréje átmenet után"
10
 QuickTransitions.SwapScenesTT="Az előnézet és a kimeneti jelenet cseréje átmenet után (ha a kimenet eredeti jelenete még létezik).\nEz nincs kihatással a kimenet eredeti jelenetére."
11
@@ -107,6 +110,8 @@
12
 Output.RecordNoSpace.Msg="Nincs elegendő lemezterület a felvétel folytatásához."
13
 Output.RecordError.Title="Felvételi hiba"
14
 Output.RecordError.Msg="Ismeretlen hiba lépett fel a felvétel során."
15
+Output.ReplayBuffer.NoHotkey.Title="Nincs gyorsbillentyű beállítva!"
16
+Output.ReplayBuffer.NoHotkey.Msg="Nincs mentés gyorsbillentyű a visszajátszási pufferhez. Kérem állítson be egy \"Mentés\" gyorsbillentyűt a visszajátszások felvételeinek mentésére."
17
 
18
 Output.BadPath.Title="A fájl elérési útja hibás"
19
 Output.BadPath.Text="A beállított elérési útvonal érvénytelen. Kérem ellenőrizze a beállításait és győződjön meg arról, hogy a fájl elérési útja érvényes."
20
@@ -262,9 +267,12 @@
21
 Basic.Main.Sources="Források"
22
 Basic.Main.Connecting="Kapcsolódás..."
23
 Basic.Main.StartRecording="Felvétel indítása"
24
+Basic.Main.StartReplayBuffer="Visszajátszás puffer indítása"
25
 Basic.Main.StartStreaming="Stream indítása"
26
 Basic.Main.StopRecording="Felvétel leállítása"
27
 Basic.Main.StoppingRecording="Felvétel leállítása..."
28
+Basic.Main.StopReplayBuffer="Visszajátszás puffer megállítása"
29
+Basic.Main.StoppingReplayBuffer="Visszajátszás puffer leáll..."
30
 Basic.Main.StopStreaming="Stream leállítása"
31
 Basic.Main.StoppingStreaming="Stream leállítása..."
32
 Basic.Main.ForceStopStreaming="Stream leállítása (Késleltetés elvetése)"
33
@@ -292,6 +300,8 @@
34
 Basic.MainMenu.Edit.Scale.Output="Kimenet (%1x%2)"
35
 Basic.MainMenu.Edit.Transform="&Alakítás"
36
 Basic.MainMenu.Edit.Transform.EditTransform="&Alakítás átszerkesztése..."
37
+Basic.MainMenu.Edit.Transform.CopyTransform="Alakítás másolása"
38
+Basic.MainMenu.Edit.Transform.PasteTransform="Átalakítás beillesztése"
39
 Basic.MainMenu.Edit.Transform.ResetTransform="&Alakítás visszaállítása"
40
 Basic.MainMenu.Edit.Transform.Rotate90CW="Forgatás 90 fokkal balra"
41
 Basic.MainMenu.Edit.Transform.Rotate90CCW="Forgatás 90 fokkal jobbra"
42
@@ -316,6 +326,12 @@
43
 
44
 Basic.MainMenu.SceneCollection="&Jelenet gyűjtemény"
45
 Basic.MainMenu.Profile="&Profil"
46
+Basic.MainMenu.Profile.Import="Profil importálása"
47
+Basic.MainMenu.Profile.Export="Profil exportálása"
48
+Basic.MainMenu.SceneCollection.Import="Jelenet gyűjtemény importálása"
49
+Basic.MainMenu.SceneCollection.Export="Jelenet gyűjtemény exportálása"
50
+Basic.MainMenu.Profile.Exists="A profil már létezik"
51
+Basic.MainMenu.SceneCollection.Exists="A jelenet gyűjtemény már létezik"
52
 
53
 Basic.MainMenu.Tools="&Eszközök"
54
 
55
@@ -362,6 +378,14 @@
56
 Basic.Settings.Output.Mode.Simple="Egyszerű"
57
 Basic.Settings.Output.Mode.Adv="Haladó"
58
 Basic.Settings.Output.Mode.FFmpeg="FFmpeg kimenet"
59
+Basic.Settings.Output.UseReplayBuffer="Visszajátszás puffer engedélyezése"
60
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Maximális visszajátszási idő (Másodperc)"
61
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Maximális memória (Megabájt)"
62
+Basic.Settings.Output.ReplayBuffer.Estimate="Becsült memóriaigény: %1 MB"
63
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Nem lehet megbecsülni a memóriaigényt. Kérem állítson be egy maximális memória limitet."
64
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Megjegyzés: Bizonyosodjon meg róla, hogy beállított egy billentyűparancsot az újrajátszás pufferre a gyorsbillentyű szekcióban)"
65
+Basic.Settings.Output.ReplayBuffer.Prefix="Visszajátszási puffer fájlév előtag"
66
+Basic.Settings.Output.ReplayBuffer.Suffix="Utótag"
67
 Basic.Settings.Output.Simple.SavePath="Felvétel helye"
68
 Basic.Settings.Output.Simple.RecordingQuality="Felvétel minősége"
69
 Basic.Settings.Output.Simple.RecordingQuality.Stream="Ugyanaz, mint a stream"
70
@@ -399,6 +423,8 @@
71
 Basic.Settings.Output.Adv.Audio.Track2="Sáv 2"
72
 Basic.Settings.Output.Adv.Audio.Track3="Sáv 3"
73
 Basic.Settings.Output.Adv.Audio.Track4="Sáv 4"
74
+Basic.Settings.Output.Adv.Audio.Track5="Sáv 5"
75
+Basic.Settings.Output.Adv.Audio.Track6="Sáv 6"
76
 
77
 Basic.Settings.Output.Adv.Recording="Rögzítés"
78
 Basic.Settings.Output.Adv.Recording.Type="Típus"
79
@@ -497,10 +523,6 @@
80
 Basic.Settings.Hotkeys="Gyorsbillentyűk"
81
 Basic.Settings.Hotkeys.Pair="Azonos billentyűkombináció a '%1' mezővel, ezért kapcsolóként működik"
82
 
83
-Basic.Hotkeys.StartStreaming="Stream indítása"
84
-Basic.Hotkeys.StopStreaming="Stream leállítása"
85
-Basic.Hotkeys.StartRecording="Felvétel indítása"
86
-Basic.Hotkeys.StopRecording="Felvétel leállítása"
87
 Basic.Hotkeys.SelectScene="Jelenethez kapcsolás"
88
 
89
 Basic.SystemTray.Show="Mutat"
90
obs-studio-0.16.6.tar.xz/UI/data/locale/it-IT.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/it-IT.ini Changed
12
 
1
@@ -497,10 +497,6 @@
2
 Basic.Settings.Hotkeys="Tasti di scelta rapida"
3
 Basic.Settings.Hotkeys.Pair="La combinazione di chiavi condivisa con '%1' funziona da commutatore"
4
 
5
-Basic.Hotkeys.StartStreaming="Inizia diretta"
6
-Basic.Hotkeys.StopStreaming="Termina diretta"
7
-Basic.Hotkeys.StartRecording="Inizia registrazione"
8
-Basic.Hotkeys.StopRecording="Ferma registrazione"
9
 Basic.Hotkeys.SelectScene="Passa alla scena"
10
 
11
 Basic.SystemTray.Show="Mostra"
12
obs-studio-0.16.6.tar.xz/UI/data/locale/ja-JP.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/ja-JP.ini Changed
90
 
1
@@ -53,6 +53,9 @@
2
 Minutes="分"
3
 Seconds="秒"
4
 Deprecated="非推奨"
5
+ReplayBuffer="リプレイバッファー"
6
+Import="インポート"
7
+Export="エクスポート"
8
 
9
 QuickTransitions.SwapScenes="トランジション後にプレビュー/出力シーンを入れ替え"
10
 QuickTransitions.SwapScenesTT="(出力のオリジナルシーンがまだ存在する場合)、トランジション後のプレビューと出力シーンを入れ替えます。\nこれは出力のオリジナルシーンに加えられた可能性があるすべての変更を元に戻しません。"
11
@@ -107,6 +110,8 @@
12
 Output.RecordNoSpace.Msg="録画を継続する十分なディスク領域がありません。"
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
@@ -262,9 +267,12 @@
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
@@ -292,6 +300,8 @@
34
 Basic.MainMenu.Edit.Scale.Output="出力(スケーリング) (%1x%2)"
35
 Basic.MainMenu.Edit.Transform="変換(&T)"
36
 Basic.MainMenu.Edit.Transform.EditTransform="変換の編集...(&E)"
37
+Basic.MainMenu.Edit.Transform.CopyTransform="変換をコピー"
38
+Basic.MainMenu.Edit.Transform.PasteTransform="変換を貼り付け"
39
 Basic.MainMenu.Edit.Transform.ResetTransform="変換をリセット(&R)"
40
 Basic.MainMenu.Edit.Transform.Rotate90CW="時計回りに 90 度回転"
41
 Basic.MainMenu.Edit.Transform.Rotate90CCW="反時計回りに 90 度回転"
42
@@ -316,6 +326,12 @@
43
 
44
 Basic.MainMenu.SceneCollection="シーンコレクション(&S)"
45
 Basic.MainMenu.Profile="プロファイル(&P)"
46
+Basic.MainMenu.Profile.Import="プロファイルをインポート"
47
+Basic.MainMenu.Profile.Export="プロファイルをエクスポート"
48
+Basic.MainMenu.SceneCollection.Import="シーンコレクションをインポート"
49
+Basic.MainMenu.SceneCollection.Export="シーンコレクションをエクスポート"
50
+Basic.MainMenu.Profile.Exists="プロファイルは既に存在します"
51
+Basic.MainMenu.SceneCollection.Exists="シーンコレクションは既に存在します"
52
 
53
 Basic.MainMenu.Tools="ツール(&T)"
54
 
55
@@ -362,6 +378,14 @@
56
 Basic.Settings.Output.Mode.Simple="基本"
57
 Basic.Settings.Output.Mode.Adv="詳細"
58
 Basic.Settings.Output.Mode.FFmpeg="FFmpeg の出力"
59
+Basic.Settings.Output.UseReplayBuffer="リプレイバッファーを有効にする"
60
+Basic.Settings.Output.ReplayBuffer.SecondsMax="最大リプレイ時間 (秒)"
61
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="最大メモリ (メガバイト)"
62
+Basic.Settings.Output.ReplayBuffer.Estimate="概算メモリ使用量: %1 MB"
63
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="メモリ使用量を見積もることができません。 最大メモリ制限を設定してください。"
64
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(注: ホットキーでリプレイバッファーのホットキーを設定してください)"
65
+Basic.Settings.Output.ReplayBuffer.Prefix="リプレイバッファーのファイル名の接頭辞"
66
+Basic.Settings.Output.ReplayBuffer.Suffix="接尾辞"
67
 Basic.Settings.Output.Simple.SavePath="録画ファイルのパス"
68
 Basic.Settings.Output.Simple.RecordingQuality="録画品質"
69
 Basic.Settings.Output.Simple.RecordingQuality.Stream="配信と同じ"
70
@@ -399,6 +423,8 @@
71
 Basic.Settings.Output.Adv.Audio.Track2="トラック 2"
72
 Basic.Settings.Output.Adv.Audio.Track3="トラック 3"
73
 Basic.Settings.Output.Adv.Audio.Track4="トラック 4"
74
+Basic.Settings.Output.Adv.Audio.Track5="トラック 5"
75
+Basic.Settings.Output.Adv.Audio.Track6="トラック 6"
76
 
77
 Basic.Settings.Output.Adv.Recording="録画"
78
 Basic.Settings.Output.Adv.Recording.Type="種別"
79
@@ -497,10 +523,6 @@
80
 Basic.Settings.Hotkeys="ホットキー"
81
 Basic.Settings.Hotkeys.Pair="'%1' との組合せでトグルスイッチとして機能します"
82
 
83
-Basic.Hotkeys.StartStreaming="配信開始"
84
-Basic.Hotkeys.StopStreaming="配信終了"
85
-Basic.Hotkeys.StartRecording="録画開始"
86
-Basic.Hotkeys.StopRecording="録画終了"
87
 Basic.Hotkeys.SelectScene="シーン切り替え"
88
 
89
 Basic.SystemTray.Show="表示"
90
obs-studio-0.16.6.tar.xz/UI/data/locale/ko-KR.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/ko-KR.ini Changed
90
 
1
@@ -53,6 +53,9 @@
2
 Minutes="분"
3
 Seconds="초"
4
 Deprecated="사용하지 않음"
5
+ReplayBuffer="리플레이 버퍼"
6
+Import="가져오기"
7
+Export="내보내기"
8
 
9
 QuickTransitions.SwapScenes="전환 후 미리 보기/출력 장면을 교체"
10
 QuickTransitions.SwapScenesTT="(만약 출력 쪽 원본 장면이 있을 때) 전환 작업 이후 미리 보기와 출력 장면을 교체합니다. \n출력 쪽 원본 장면에서 변경한 내용은 사라지지 않습니다."
11
@@ -107,6 +110,8 @@
12
 Output.RecordNoSpace.Msg="녹화를 계속하기 위한 디스크 공간이 부족합니다."
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
@@ -262,9 +267,12 @@
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
@@ -292,6 +300,8 @@
34
 Basic.MainMenu.Edit.Scale.Output="출력 (%1x%2)"
35
 Basic.MainMenu.Edit.Transform="변환(&T)"
36
 Basic.MainMenu.Edit.Transform.EditTransform="변환 편집(&E)"
37
+Basic.MainMenu.Edit.Transform.CopyTransform="변환 복사"
38
+Basic.MainMenu.Edit.Transform.PasteTransform="변환 붙여넣기"
39
 Basic.MainMenu.Edit.Transform.ResetTransform="변환 초기화(&R)"
40
 Basic.MainMenu.Edit.Transform.Rotate90CW="시계 방향으로 90도 회전"
41
 Basic.MainMenu.Edit.Transform.Rotate90CCW="반시계 방향으로 90도 회전"
42
@@ -316,6 +326,12 @@
43
 
44
 Basic.MainMenu.SceneCollection="장면 모음(&S)"
45
 Basic.MainMenu.Profile="프로파일(&P)"
46
+Basic.MainMenu.Profile.Import="프로파일 가져오기"
47
+Basic.MainMenu.Profile.Export="프로파일 내보내기"
48
+Basic.MainMenu.SceneCollection.Import="장면 모음 가져오기"
49
+Basic.MainMenu.SceneCollection.Export="장면 모음 내보내기"
50
+Basic.MainMenu.Profile.Exists="그 프로파일은 이미 존재합니다."
51
+Basic.MainMenu.SceneCollection.Exists="그 장면 모음은 이미 존재합니다."
52
 
53
 Basic.MainMenu.Tools="도구(&T)"
54
 
55
@@ -362,6 +378,14 @@
56
 Basic.Settings.Output.Mode.Simple="단순"
57
 Basic.Settings.Output.Mode.Adv="고급"
58
 Basic.Settings.Output.Mode.FFmpeg="FFmpeg 출력"
59
+Basic.Settings.Output.UseReplayBuffer="리플레이 버퍼 활성화"
60
+Basic.Settings.Output.ReplayBuffer.SecondsMax="최대 리플레이 시간 (초 단위)"
61
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="최대 메모리 (메가바이트 단위)"
62
+Basic.Settings.Output.ReplayBuffer.Estimate="예상되는 메모리 사용량: %1 MB"
63
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="메모리 사용량을 계산할 수 없습니다. 최대 메모리 사용량을 설정하세요."
64
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(참고: 단축키 설정에서 리플레이 버퍼의 단축키를 꼭 지정하세요)"
65
+Basic.Settings.Output.ReplayBuffer.Prefix="리플레이 버퍼 파일이름 접두사"
66
+Basic.Settings.Output.ReplayBuffer.Suffix="접미사"
67
 Basic.Settings.Output.Simple.SavePath="녹화 경로"
68
 Basic.Settings.Output.Simple.RecordingQuality="녹화 품질"
69
 Basic.Settings.Output.Simple.RecordingQuality.Stream="방송 품질과 동일하게"
70
@@ -399,6 +423,8 @@
71
 Basic.Settings.Output.Adv.Audio.Track2="트랙 2"
72
 Basic.Settings.Output.Adv.Audio.Track3="트랙 3"
73
 Basic.Settings.Output.Adv.Audio.Track4="트랙 4"
74
+Basic.Settings.Output.Adv.Audio.Track5="트랙 5"
75
+Basic.Settings.Output.Adv.Audio.Track6="트랙 6"
76
 
77
 Basic.Settings.Output.Adv.Recording="녹화"
78
 Basic.Settings.Output.Adv.Recording.Type="형식"
79
@@ -497,10 +523,6 @@
80
 Basic.Settings.Hotkeys="단축키"
81
 Basic.Settings.Hotkeys.Pair="'%1'과 공유하는 키 조합을 토글 형식으로 설정"
82
 
83
-Basic.Hotkeys.StartStreaming="방송 시작"
84
-Basic.Hotkeys.StopStreaming="방송 중단"
85
-Basic.Hotkeys.StartRecording="녹화 시작"
86
-Basic.Hotkeys.StopRecording="녹화 중단"
87
 Basic.Hotkeys.SelectScene="장면 전환"
88
 
89
 Basic.SystemTray.Show="보이기"
90
obs-studio-0.16.6.tar.xz/UI/data/locale/ms-MY.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/ms-MY.ini Changed
11
 
1
@@ -384,9 +384,6 @@
2
 
3
 Basic.Settings.Hotkeys="Kekunci Pantas"
4
 
5
-Basic.Hotkeys.StartStreaming="Mula 'Streaming'"
6
-Basic.Hotkeys.StartRecording="Mula Rakaman"
7
-Basic.Hotkeys.StopRecording="Hentikan Rakaman"
8
 
9
 Basic.SystemTray.Show="Papar"
10
 Basic.SystemTray.Hide="Sembunyi"
11
obs-studio-0.16.6.tar.xz/UI/data/locale/nb-NO.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/nb-NO.ini Changed
12
 
1
@@ -464,10 +464,6 @@
2
 Basic.Settings.Hotkeys="Hurtigtaster"
3
 Basic.Settings.Hotkeys.Pair="Tastekombinasjoner delt med '%1' vil veksle"
4
 
5
-Basic.Hotkeys.StartStreaming="Start strømming"
6
-Basic.Hotkeys.StopStreaming="Stopp strømming"
7
-Basic.Hotkeys.StartRecording="Start opptak"
8
-Basic.Hotkeys.StopRecording="Stopp opptak"
9
 Basic.Hotkeys.SelectScene="Bytt til scene"
10
 
11
 
12
obs-studio-0.16.6.tar.xz/UI/data/locale/nl-NL.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/nl-NL.ini Changed
97
 
1
@@ -52,6 +52,10 @@
2
 Hours="Uren"
3
 Minutes="Minuten"
4
 Seconds="Seconden"
5
+Deprecated="Verouderd"
6
+ReplayBuffer="Replay Buffer"
7
+Import="Importeer"
8
+Export="Exporteer"
9
 
10
 QuickTransitions.SwapScenes="Preview-/uitvoerscenes verwisselen na overgang"
11
 QuickTransitions.SwapScenesTT="Verwisselt de preview- en uitvoercenes na een overgang (als de originele uitvoerscène nog bestaat.)\nDit zal geen veranderingen ongedaan maken die mogelijk zijn gemaakt aan de originele uitvoerscène."
12
@@ -106,6 +110,8 @@
13
 Output.RecordNoSpace.Msg="Er is niet voldoende schijfruimte om door te gaan met opnemen."
14
 Output.RecordError.Title="Opnamefout"
15
 Output.RecordError.Msg="Er is een onbekende fout opgetreden tijdens het opnemen."
16
+Output.ReplayBuffer.NoHotkey.Title="Er is geen sneltoets ingesteld!"
17
+Output.ReplayBuffer.NoHotkey.Msg="Er is geen opslaan sneltoets ingesteld voor de replay buffer. Zet aub de \"Opslaan\" sneltoets voor het opslaan van replay-opnames."
18
 
19
 Output.BadPath.Title="Ongeldig Bestandspad"
20
 Output.BadPath.Text="Het geconfigureerde bestandsuitvoerpad is ongeldig. Controleer a.u.b. je instellingen om te bevestigen dat er een geldig bestandspad is ingesteld."
21
@@ -261,9 +267,12 @@
22
 Basic.Main.Sources="Bronnen"
23
 Basic.Main.Connecting="Verbinden..."
24
 Basic.Main.StartRecording="Opname Starten"
25
+Basic.Main.StartReplayBuffer="Start Replay Buffer"
26
 Basic.Main.StartStreaming="Stream Starten"
27
 Basic.Main.StopRecording="Opname Stoppen"
28
 Basic.Main.StoppingRecording="Opname Stoppen..."
29
+Basic.Main.StopReplayBuffer="Stop Replay Buffer"
30
+Basic.Main.StoppingReplayBuffer="Replay Buffer aan het stoppen..."
31
 Basic.Main.StopStreaming="Stream Stoppen"
32
 Basic.Main.StoppingStreaming="Stream Stoppen..."
33
 Basic.Main.ForceStopStreaming="Stop Stream (vertraging negeren)"
34
@@ -285,8 +294,14 @@
35
 Basic.MainMenu.Edit.UndoAction="$1 ongedaan maken (&U)"
36
 Basic.MainMenu.Edit.RedoAction="$1 opnieuw toepassen (&R)"
37
 Basic.MainMenu.Edit.LockPreview="Preview vergrende&len"
38
+Basic.MainMenu.Edit.Scale="Preview &schalen"
39
+Basic.MainMenu.Edit.Scale.Window="Schaal naar venster"
40
+Basic.MainMenu.Edit.Scale.Canvas="Canvas (%1x%2)"
41
+Basic.MainMenu.Edit.Scale.Output="Uitvoer (%1x%2)"
42
 Basic.MainMenu.Edit.Transform="&Transformeren"
43
 Basic.MainMenu.Edit.Transform.EditTransform="Transformatie bewerken... (&E)"
44
+Basic.MainMenu.Edit.Transform.CopyTransform="Kopieer transformatie"
45
+Basic.MainMenu.Edit.Transform.PasteTransform="Plak transformatie"
46
 Basic.MainMenu.Edit.Transform.ResetTransform="Transformatie herstellen (&R)"
47
 Basic.MainMenu.Edit.Transform.Rotate90CW="Rechtsom kantelen"
48
 Basic.MainMenu.Edit.Transform.Rotate90CCW="Linksom kantelen"
49
@@ -311,6 +326,12 @@
50
 
51
 Basic.MainMenu.SceneCollection="&Scèneverzameling"
52
 Basic.MainMenu.Profile="&Profiel"
53
+Basic.MainMenu.Profile.Import="Importeer profiel"
54
+Basic.MainMenu.Profile.Export="Exporteer profiel"
55
+Basic.MainMenu.SceneCollection.Import="Importeer scèneverzameling"
56
+Basic.MainMenu.SceneCollection.Export="Exporteer scèneverzameling"
57
+Basic.MainMenu.Profile.Exists="Het profiel bestaat al"
58
+Basic.MainMenu.SceneCollection.Exists="De scèneverzameling bestaat al"
59
 
60
 Basic.MainMenu.Tools="&Tools"
61
 
62
@@ -357,6 +378,14 @@
63
 Basic.Settings.Output.Mode.Simple="Simpel"
64
 Basic.Settings.Output.Mode.Adv="Geavanceerd"
65
 Basic.Settings.Output.Mode.FFmpeg="FFmpeg-uitvoer"
66
+Basic.Settings.Output.UseReplayBuffer="Replay Buffer Inschakelen"
67
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Maximale Replay-tijd (Seconden)"
68
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Maximale hoeveelheid geheugen (Megabytes)"
69
+Basic.Settings.Output.ReplayBuffer.Estimate="Geschat geheugengebruik: %1 MB"
70
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Kan geheugengebruik niet inschatten. Stel een limiet in op het geheugengebruik."
71
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Let op: Maak een sneltoets voor de replay buffer in de Sneltoetsen sectie)"
72
+Basic.Settings.Output.ReplayBuffer.Prefix="Replay Buffer Bestandsnaam Prefix"
73
+Basic.Settings.Output.ReplayBuffer.Suffix="Achtervoegsel"
74
 Basic.Settings.Output.Simple.SavePath="Opnamepad"
75
 Basic.Settings.Output.Simple.RecordingQuality="Opnamekwaliteit"
76
 Basic.Settings.Output.Simple.RecordingQuality.Stream="Hetzelfde als de stream"
77
@@ -394,6 +423,8 @@
78
 Basic.Settings.Output.Adv.Audio.Track2="Spoor 2"
79
 Basic.Settings.Output.Adv.Audio.Track3="Spoor 3"
80
 Basic.Settings.Output.Adv.Audio.Track4="Spoor 4"
81
+Basic.Settings.Output.Adv.Audio.Track5="Spoor 5"
82
+Basic.Settings.Output.Adv.Audio.Track6="Spoor 6"
83
 
84
 Basic.Settings.Output.Adv.Recording="Opnemen"
85
 Basic.Settings.Output.Adv.Recording.Type="Type"
86
@@ -492,10 +523,6 @@
87
 Basic.Settings.Hotkeys="Sneltoetsen"
88
 Basic.Settings.Hotkeys.Pair="Toetsencombinaties gedeeld met '%1' werken als toggle"
89
 
90
-Basic.Hotkeys.StartStreaming="Stream Starten"
91
-Basic.Hotkeys.StopStreaming="Stream Stoppen"
92
-Basic.Hotkeys.StartRecording="Opname Starten"
93
-Basic.Hotkeys.StopRecording="Opname Stoppen"
94
 Basic.Hotkeys.SelectScene="Wissel naar scène"
95
 
96
 Basic.SystemTray.Show="Weergeven"
97
obs-studio-0.16.6.tar.xz/UI/data/locale/pl-PL.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/pl-PL.ini Changed
97
 
1
@@ -52,6 +52,10 @@
2
 Hours="Godziny"
3
 Minutes="Minuty"
4
 Seconds="Sekundy"
5
+Deprecated="Wycofywane"
6
+ReplayBuffer="Buffer replayu"
7
+Import="Importuj"
8
+Export="Eksportuj"
9
 
10
 QuickTransitions.SwapScenes="Zamień podgląd/wyjście scen po przejściu"
11
 QuickTransitions.SwapScenesTT="Zamienia podgląd i wyjście scen po przejściu (jeżeli wyjście oryginalnej sceny istnieje).\nNie przywraca to zmian jakie zostały dokonane w oryginalnej scenie."
12
@@ -106,6 +110,8 @@
13
 Output.RecordNoSpace.Msg="Za mało miejsca na dysku, aby kontynuować nagrywanie."
14
 Output.RecordError.Title="Błąd nagrywania"
15
 Output.RecordError.Msg="Wystąpił nieokreślony błąd podczas nagrywania."
16
+Output.ReplayBuffer.NoHotkey.Title="Brak klawisza skrótu!"
17
+Output.ReplayBuffer.NoHotkey.Msg="Klawisz skrótu nie jest zapisany dla buforu replay. Ustaw skrót  \"Zapisz\" aby zapisać nagrania replay."
18
 
19
 Output.BadPath.Title="Nieprawidłowa ścieżka pliku"
20
 Output.BadPath.Text="Ustawiona ścieżka pliku wynikowego jest nieprawidłowa. Proszę sprawdzić ustawienia."
21
@@ -261,9 +267,12 @@
22
 Basic.Main.Sources="Źródła obrazu"
23
 Basic.Main.Connecting="Łączenie..."
24
 Basic.Main.StartRecording="Rozpocznij nagrywanie"
25
+Basic.Main.StartReplayBuffer="Rozpocznij bufor replayu"
26
 Basic.Main.StartStreaming="Rozpocznij stream"
27
 Basic.Main.StopRecording="Zatrzymaj nagrywanie"
28
 Basic.Main.StoppingRecording="Zatrzymywanie nagrywania..."
29
+Basic.Main.StopReplayBuffer="Zatrzymaj bufor replayu"
30
+Basic.Main.StoppingReplayBuffer="Zatrzymywanie buforu replay..."
31
 Basic.Main.StopStreaming="Zatrzymaj stream"
32
 Basic.Main.StoppingStreaming="Zatrzymywanie streamowania..."
33
 Basic.Main.ForceStopStreaming="Zatrzymaj stream (anuluj opóźnienie)"
34
@@ -285,8 +294,14 @@
35
 Basic.MainMenu.Edit.UndoAction="&Cofnij $1"
36
 Basic.MainMenu.Edit.RedoAction="&Wykonaj ponownie $1"
37
 Basic.MainMenu.Edit.LockPreview="Zab&lokuj podgląd"
38
+Basic.MainMenu.Edit.Scale="&Skalowanie widoku"
39
+Basic.MainMenu.Edit.Scale.Window="Skaluj do okna"
40
+Basic.MainMenu.Edit.Scale.Canvas="Powierzchnia robocza (%1x%2)"
41
+Basic.MainMenu.Edit.Scale.Output="Powierzchnia wyjściowa (%1x%2)"
42
 Basic.MainMenu.Edit.Transform="&Przekształcanie obrazu"
43
 Basic.MainMenu.Edit.Transform.EditTransform="&Edycja przekształceń..."
44
+Basic.MainMenu.Edit.Transform.CopyTransform="Skopiuj transformacje"
45
+Basic.MainMenu.Edit.Transform.PasteTransform="Wklej transformacje"
46
 Basic.MainMenu.Edit.Transform.ResetTransform="&Reset przekształceń"
47
 Basic.MainMenu.Edit.Transform.Rotate90CW="Obróć o 90 stopni zgodnie z ruchem wskazówkek zegara"
48
 Basic.MainMenu.Edit.Transform.Rotate90CCW="Obróć o 90 stopni przeciwnie do ruchu wskazówek zegara"
49
@@ -311,6 +326,12 @@
50
 
51
 Basic.MainMenu.SceneCollection="Zbiór &scen"
52
 Basic.MainMenu.Profile="P&rofil"
53
+Basic.MainMenu.Profile.Import="Importuj profil"
54
+Basic.MainMenu.Profile.Export="Eksportuj profil"
55
+Basic.MainMenu.SceneCollection.Import="Importuj kolekcje sceny"
56
+Basic.MainMenu.SceneCollection.Export="Exportuj kolekcje sceny"
57
+Basic.MainMenu.Profile.Exists="Profil już istnieje"
58
+Basic.MainMenu.SceneCollection.Exists="Kolekcja sceny już istnieje"
59
 
60
 Basic.MainMenu.Tools="&Narzędzia"
61
 
62
@@ -357,6 +378,14 @@
63
 Basic.Settings.Output.Mode.Simple="Proste"
64
 Basic.Settings.Output.Mode.Adv="Zaawansowane"
65
 Basic.Settings.Output.Mode.FFmpeg="Wyjście FFmpeg"
66
+Basic.Settings.Output.UseReplayBuffer="Włącz bufor replay"
67
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Maksymalny czas replay (w sekundach)"
68
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Maksymalna ilość pamięci (w megabajtach)"
69
+Basic.Settings.Output.ReplayBuffer.Estimate="Szacowane użycie pamięci: %1 MB"
70
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Nie można oszacować użycie pamięci.  Należy ustawić limit maksymalnej pamięci."
71
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Uwaga: Upewnij się aby ustawić klawisz skrótu dla buforu replay w sekcji Skróty klawiszowe)"
72
+Basic.Settings.Output.ReplayBuffer.Prefix="Prefiks nazwy pliku buforu replay"
73
+Basic.Settings.Output.ReplayBuffer.Suffix="Sufiks"
74
 Basic.Settings.Output.Simple.SavePath="Ścieżka pliku"
75
 Basic.Settings.Output.Simple.RecordingQuality="Jakość nagrywania"
76
 Basic.Settings.Output.Simple.RecordingQuality.Stream="Taki sam jak stream"
77
@@ -394,6 +423,8 @@
78
 Basic.Settings.Output.Adv.Audio.Track2="Ścieżka 2"
79
 Basic.Settings.Output.Adv.Audio.Track3="Ścieżka 3"
80
 Basic.Settings.Output.Adv.Audio.Track4="Ścieżka 4"
81
+Basic.Settings.Output.Adv.Audio.Track5="Ścieżka 5"
82
+Basic.Settings.Output.Adv.Audio.Track6="Ścieżka 6"
83
 
84
 Basic.Settings.Output.Adv.Recording="Nagrywanie"
85
 Basic.Settings.Output.Adv.Recording.Type="Typ"
86
@@ -492,10 +523,6 @@
87
 Basic.Settings.Hotkeys="Skróty klawiszowe"
88
 Basic.Settings.Hotkeys.Pair="Komibnacje klawiszy wspólne z '%1' działają jako przełączniki"
89
 
90
-Basic.Hotkeys.StartStreaming="Rozpocznij stream"
91
-Basic.Hotkeys.StopStreaming="Zakończ stream"
92
-Basic.Hotkeys.StartRecording="Rozpocznij nagrywanie"
93
-Basic.Hotkeys.StopRecording="Zatrzymaj nagrywanie"
94
 Basic.Hotkeys.SelectScene="Przełącz na scenę"
95
 
96
 Basic.SystemTray.Show="Pokaż"
97
obs-studio-0.16.6.tar.xz/UI/data/locale/pt-BR.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/pt-BR.ini Changed
12
 
1
@@ -495,10 +495,6 @@
2
 Basic.Settings.Hotkeys="Teclas de atalho"
3
 Basic.Settings.Hotkeys.Pair="Combinações de teclas compartilhadas com '%1' agem como alternaçoes"
4
 
5
-Basic.Hotkeys.StartStreaming="Iniciar transmissão"
6
-Basic.Hotkeys.StopStreaming="Parar transmissão"
7
-Basic.Hotkeys.StartRecording="Iniciar gravação"
8
-Basic.Hotkeys.StopRecording="Parar gravação"
9
 Basic.Hotkeys.SelectScene="Mudar de cena"
10
 
11
 Basic.SystemTray.Show="Exibir"
12
obs-studio-0.16.6.tar.xz/UI/data/locale/pt-PT.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/pt-PT.ini Changed
12
 
1
@@ -472,10 +472,6 @@
2
 Basic.Settings.Hotkeys="Teclas de atalho"
3
 Basic.Settings.Hotkeys.Pair="Combinações de teclas partilhadas com '%1' atuam como alavancas"
4
 
5
-Basic.Hotkeys.StartStreaming="Iniciar transmissão"
6
-Basic.Hotkeys.StopStreaming="Parar transmissão"
7
-Basic.Hotkeys.StartRecording="Iniciar gravação"
8
-Basic.Hotkeys.StopRecording="Parar gravação"
9
 Basic.Hotkeys.SelectScene="Mudar para cena"
10
 
11
 Basic.SystemTray.Show="Mostrar"
12
obs-studio-0.16.6.tar.xz/UI/data/locale/ro-RO.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/ro-RO.ini Changed
12
 
1
@@ -455,10 +455,6 @@
2
 Basic.Settings.Hotkeys="Taste rapide"
3
 Basic.Settings.Hotkeys.Pair="Combinațiile de taste partajate cu '%1' acționează ca comutatoare"
4
 
5
-Basic.Hotkeys.StartStreaming="Pornește streamingul"
6
-Basic.Hotkeys.StopStreaming="Oprește streamingul"
7
-Basic.Hotkeys.StartRecording="Pornește înregistrarea"
8
-Basic.Hotkeys.StopRecording="Oprește înregistrarea"
9
 Basic.Hotkeys.SelectScene="Comută la scenă"
10
 
11
 
12
obs-studio-0.16.6.tar.xz/UI/data/locale/ru-RU.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/ru-RU.ini Changed
38
 
1
@@ -106,6 +106,7 @@
2
 Output.RecordNoSpace.Msg="На диске недостаточно места для продолжения записи."
3
 Output.RecordError.Title="Ошибка записи"
4
 Output.RecordError.Msg="Во время записи произошла неопознанная ошибка."
5
+Output.ReplayBuffer.NoHotkey.Title="Нет набора горячих клавиш!"
6
 
7
 Output.BadPath.Title="Неправильный путь к файлу"
8
 Output.BadPath.Text="Некорректный путь к файлу.  Пожалуйста, проверьте настройки, чтобы убедиться в корректности установленного пути."
9
@@ -285,6 +286,8 @@
10
 Basic.MainMenu.Edit.UndoAction="&Отменить $1"
11
 Basic.MainMenu.Edit.RedoAction="&Повторить $1"
12
 Basic.MainMenu.Edit.LockPreview="&Заблокировать предпросмотр"
13
+Basic.MainMenu.Edit.Scale="Просмотр и масштабирование"
14
+Basic.MainMenu.Edit.Scale.Window="Масштаб окна"
15
 Basic.MainMenu.Edit.Transform="&Преобразовать"
16
 Basic.MainMenu.Edit.Transform.EditTransform="&Изменить преобразование..."
17
 Basic.MainMenu.Edit.Transform.ResetTransform="&Сбросить преобразование"
18
@@ -357,6 +360,8 @@
19
 Basic.Settings.Output.Mode.Simple="Простой"
20
 Basic.Settings.Output.Mode.Adv="Расширенные"
21
 Basic.Settings.Output.Mode.FFmpeg="Вывод FFmpeg"
22
+Basic.Settings.Output.ReplayBuffer.Estimate="Предполагаемое использование памяти: %1 МБ"
23
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Невозможно оценить использование памяти.  Пожалуйста, установите максимальный объем памяти."
24
 Basic.Settings.Output.Simple.SavePath="Путь к записи"
25
 Basic.Settings.Output.Simple.RecordingQuality="Качество записи"
26
 Basic.Settings.Output.Simple.RecordingQuality.Stream="То же, что у трансляции"
27
@@ -492,10 +497,6 @@
28
 Basic.Settings.Hotkeys="Горячие клавиши"
29
 Basic.Settings.Hotkeys.Pair="Сочетания клавиш вместе с '%1' действуют как переключатели"
30
 
31
-Basic.Hotkeys.StartStreaming="Запустить трансляцию"
32
-Basic.Hotkeys.StopStreaming="Остановить трансляцию"
33
-Basic.Hotkeys.StartRecording="Начать запись"
34
-Basic.Hotkeys.StopRecording="Остановить запись"
35
 Basic.Hotkeys.SelectScene="Перейти на сцену"
36
 
37
 Basic.SystemTray.Show="Показать"
38
obs-studio-0.16.6.tar.xz/UI/data/locale/sr-CS.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/sr-CS.ini Changed
31
 
1
@@ -52,6 +52,7 @@
2
 Hours="Sati"
3
 Minutes="Minuta"
4
 Seconds="Sekundi"
5
+Deprecated="Prevaziđeno"
6
 
7
 QuickTransitions.SwapScenes="Zameni scene pregleda/izlaza nakon prelaza"
8
 QuickTransitions.SwapScenesTT="Zamenjuje scene pregleda i izlaza nakon prelaza (ako originalna scena izlaza još uvek postoji).\nOvo neće poništiti promene koje su načinjene nad originalnom scenom izlaza."
9
@@ -285,6 +286,10 @@
10
 Basic.MainMenu.Edit.UndoAction="Vrati $1 (&U)"
11
 Basic.MainMenu.Edit.RedoAction="U&radi ponovo $1"
12
 Basic.MainMenu.Edit.LockPreview="Zak&ljučaj prikaz"
13
+Basic.MainMenu.Edit.Scale="Pregled &skaliranja"
14
+Basic.MainMenu.Edit.Scale.Window="Skaliraj na veličinu prozora"
15
+Basic.MainMenu.Edit.Scale.Canvas="Platno (%1x%2)"
16
+Basic.MainMenu.Edit.Scale.Output="Izlaz (%1x%2)"
17
 Basic.MainMenu.Edit.Transform="&Transformiši"
18
 Basic.MainMenu.Edit.Transform.EditTransform="Izm&eni transformaciju..."
19
 Basic.MainMenu.Edit.Transform.ResetTransform="Poništi t&ransformaciju"
20
@@ -492,10 +497,6 @@
21
 Basic.Settings.Hotkeys="Prečice"
22
 Basic.Settings.Hotkeys.Pair="Kombinacije tastera deljene sa '%1' se ponašaju kao prekidači"
23
 
24
-Basic.Hotkeys.StartStreaming="Započni strimovanje"
25
-Basic.Hotkeys.StopStreaming="Zaustavi strimovanje"
26
-Basic.Hotkeys.StartRecording="Počni snimanje"
27
-Basic.Hotkeys.StopRecording="Zaustavi snimanje"
28
 Basic.Hotkeys.SelectScene="Prebaci na scenu"
29
 
30
 Basic.SystemTray.Show="Prikaži"
31
obs-studio-0.16.6.tar.xz/UI/data/locale/sr-SP.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/sr-SP.ini Changed
31
 
1
@@ -52,6 +52,7 @@
2
 Hours="Сати"
3
 Minutes="Минута"
4
 Seconds="Секунди"
5
+Deprecated="Превазиђено"
6
 
7
 QuickTransitions.SwapScenes="Замени сцене прегледа/излаза након прелаза"
8
 QuickTransitions.SwapScenesTT="Замењује сцене прегледа и излаза након прелаза (ако оригинална сцена још увек постоји).\nОво неће поништити промене које су начињене над оригиналном сценом излаза."
9
@@ -285,6 +286,10 @@
10
 Basic.MainMenu.Edit.UndoAction="Врати $1 (&U)"
11
 Basic.MainMenu.Edit.RedoAction="Уради поново $1 (&R)"
12
 Basic.MainMenu.Edit.LockPreview="Закључај приказ (&L)"
13
+Basic.MainMenu.Edit.Scale="Преглед скалирања (&s)"
14
+Basic.MainMenu.Edit.Scale.Window="Скалирај на величину прозора"
15
+Basic.MainMenu.Edit.Scale.Canvas="Платно (%1x%2)"
16
+Basic.MainMenu.Edit.Scale.Output="Излаз (%1x%2)"
17
 Basic.MainMenu.Edit.Transform="&Трансформиши"
18
 Basic.MainMenu.Edit.Transform.EditTransform="Изм&ени трансформацију..."
19
 Basic.MainMenu.Edit.Transform.ResetTransform="Поништи трансформацију (&R)"
20
@@ -492,10 +497,6 @@
21
 Basic.Settings.Hotkeys="Пречице"
22
 Basic.Settings.Hotkeys.Pair="Комбинације тастера дељене са '%1' се понашају као прекидачи"
23
 
24
-Basic.Hotkeys.StartStreaming="Почни стримовање"
25
-Basic.Hotkeys.StopStreaming="Заустави стримовање"
26
-Basic.Hotkeys.StartRecording="Почни снимање"
27
-Basic.Hotkeys.StopRecording="Заустави снимање"
28
 Basic.Hotkeys.SelectScene="Пребаци на сцену"
29
 
30
 Basic.SystemTray.Show="Прикажи"
31
obs-studio-0.16.6.tar.xz/UI/data/locale/sv-SE.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/sv-SE.ini Changed
29
 
1
@@ -107,6 +107,7 @@
2
 Output.RecordNoSpace.Msg="Det finns inte tillräckligt med diskutrymme för att fortsätta inspelningen."
3
 Output.RecordError.Title="Inspelningsfel"
4
 Output.RecordError.Msg="Ett okänt fel uppstod vid inspelning."
5
+Output.ReplayBuffer.NoHotkey.Title="Ingen angivet kortkommando!"
6
 
7
 Output.BadPath.Title="Ogiltig sökväg"
8
 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."
9
@@ -362,6 +363,8 @@
10
 Basic.Settings.Output.Mode.Simple="Simpel"
11
 Basic.Settings.Output.Mode.Adv="Avancerat"
12
 Basic.Settings.Output.Mode.FFmpeg="FFmpeg-utmatning"
13
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Maximalt minne (Megabyte)"
14
+Basic.Settings.Output.ReplayBuffer.Estimate="Uppskattad minnesanvändning: %1 MB"
15
 Basic.Settings.Output.Simple.SavePath="Inspelningssökväg"
16
 Basic.Settings.Output.Simple.RecordingQuality="Inspelningskvalitet"
17
 Basic.Settings.Output.Simple.RecordingQuality.Stream="Samma som ström"
18
@@ -496,10 +499,6 @@
19
 Basic.Settings.Hotkeys="Kortkommandon"
20
 Basic.Settings.Hotkeys.Pair="Tangentkombinationer som delas med \"%1\" fungerar som strömbrytare"
21
 
22
-Basic.Hotkeys.StartStreaming="Börja strömma"
23
-Basic.Hotkeys.StopStreaming="Sluta strömma"
24
-Basic.Hotkeys.StartRecording="Starta inspelning"
25
-Basic.Hotkeys.StopRecording="Stoppa inspelning"
26
 Basic.Hotkeys.SelectScene="Byt till scen"
27
 
28
 Basic.SystemTray.Show="Visa"
29
obs-studio-0.16.6.tar.xz/UI/data/locale/th-TH.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/th-TH.ini Changed
36
 
1
@@ -5,19 +5,34 @@
2
 OK="ตกลง"
3
 Apply="นำไปใช้"
4
 Cancel="ยกเลิก"
5
+Close="ปิด"
6
+Save="บันทึก"
7
+Discard="ละทิ้ง"
8
+Disable="ไม่ใช้"
9
 Yes="ใช่"
10
 No="ไม่"
11
 Add="เพิ่ม"
12
 Remove="ลบ"
13
 Rename="เปลี่ยนชื่อ"
14
+Filters="ฟิลเตอร์"
15
 Properties="คุณสมบัติ"
16
 MoveUp="เลื่อนขึ้น"
17
 MoveDown="เลื่อนลง"
18
 Settings="ตั้งค่า"
19
+Display="แสดงผล"
20
+Name="ชื่อ"
21
 Exit="ออก"
22
 Browse="เปิดหา"
23
 Mono="โมโน"
24
 Stereo="สเตอริโอ"
25
+PreviewProjector="แสดงผลแบบเต็มจอ (ตัวอย่าง)"
26
+Clear="ล้าง"
27
+Revert="กลับค่าเดิม"
28
+Show="แสดง"
29
+Hide="ซ่อน"
30
+Untitled="ไม่มีชื่อ"
31
+New="ใหม่"
32
+Enable="เปิดใช้งาน"
33
 
34
 
35
 
36
obs-studio-0.16.6.tar.xz/UI/data/locale/tr-TR.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/tr-TR.ini Changed
319
 
1
@@ -40,16 +40,35 @@
2
 Duplicate="Çoğalt"
3
 Enable="Etkinleştir"
4
 DisableOSXVSync="OSX V-Sync Devre Dışı Bırakma"
5
+HighResourceUsage="Kodlama aşırı yüklendi!  Video ayarlarını kapatmayı veya daha hızlı bir kodlama ön ayarını kullanmayı düşünün."
6
 Transition="Geçiş"
7
 QuickTransitions="Hızlı Geçiş"
8
 Left="Sol"
9
 Right="Sağ"
10
 Top="Üst"
11
 Bottom="Alt"
12
-
13
-
14
+Reset="Sıfırla"
15
+Hours="Saat"
16
+Minutes="Dakika"
17
+Seconds="Saniye"
18
+Deprecated="Kullanım dışı"
19
+ReplayBuffer="Tekrar Oynatma Arabelleği"
20
+Import="İçe Aktar"
21
+Export="Dışa Aktar"
22
+
23
+QuickTransitions.DuplicateScene="Sahneyi Çoğalt"
24
+QuickTransitions.EditProperties="Kaynakları Çoğalt"
25
+QuickTransitions.HotkeyName="Hızlı Geçiş: %1"
26
+
27
+Basic.AddTransition="Yapılandırılabilir Geçiş Ekle"
28
+Basic.RemoveTransition="Yapılandırılabilir Geçiş Kaldır"
29
+Basic.TransitionProperties="Geçiş Özellikleri"
30
+Basic.SceneTransitions="Sahne Geçişleri"
31
 Basic.TransitionDuration="Süre"
32
+Basic.TogglePreviewProgramMode="Stüdyo Modu"
33
 
34
+TransitionNameDlg.Text="Lütfen geçiş adını girin"
35
+TransitionNameDlg.Title="Geçiş Adı"
36
 
37
 TitleBar.Profile="Profil"
38
 TitleBar.Scenes="Sahneler"
39
@@ -60,13 +79,18 @@
40
 NoNameEntered.Title="Lütfen geçerli bir isim girin"
41
 NoNameEntered.Text="İsmi boş kullanamazsınız."
42
 
43
+ConfirmStart.Title="Yayın Başlatılsın Mı?"
44
+ConfirmStart.Text="Yayını gerçekten başlatmak istiyor musunuz?"
45
 
46
+ConfirmStop.Title="Yayın Durdurulsun Mu?"
47
+ConfirmStop.Text="Yayını gerçekten durdurmak istiyor musunuz?"
48
 
49
 ConfirmExit.Title="OBS'den Çıkılsın mı?"
50
 ConfirmExit.Text="OBS şu anda etkin. Tüm yayınlar / kayıtlar kapatılacak. Çıkmak istediğinize emin misiniz?"
51
 
52
 ConfirmRemove.Title="Kaldırmayı Onayla"
53
 ConfirmRemove.Text="'$1''i kaldırmak istediğinizden emin misiniz?"
54
+ConfirmRemove.TextMultiple="%1 öğeyi kaldırmak istediğinizden emin misiniz?"
55
 
56
 Output.ConnectFail.Title="Bağlantı kurulamadı"
57
 Output.ConnectFail.BadPath="Bağlantı adresiniz geçersiz. Ayarlarınızı kontrol edin ve geçerli bir adres giriniz."
58
@@ -80,6 +104,7 @@
59
 Output.RecordNoSpace.Msg="Kayıt'aa devam etmek yeterli disk alanı yok."
60
 Output.RecordError.Title="Kayıt Hatası"
61
 Output.RecordError.Msg="Kayıt anında bir hata oluştu."
62
+Output.ReplayBuffer.NoHotkey.Title="Kısayol tuşu ayarlanmadı!"
63
 
64
 Output.BadPath.Title="Dosya Yolu Geçersiz"
65
 Output.BadPath.Text="Ayarlanan dosya kayıt yolu geçersiz. Lütfen ayarlarınızı kontrol ederek geçerli bir dosya yolunun girilmiş olduğundan emin olunuz."
66
@@ -123,7 +148,23 @@
67
 
68
 Basic.Main.PreviewConextMenu.Enable="Önizlemeyi Etkinleştir"
69
 
70
-
71
+ScaleFiltering="Ölçek Filtreleme"
72
+ScaleFiltering.Point="Nokta"
73
+ScaleFiltering.Bilinear="Bilinear"
74
+ScaleFiltering.Bicubic="Bicubic"
75
+ScaleFiltering.Lanczos="Lanczos"
76
+
77
+Deinterlacing="Deinterlacing"
78
+Deinterlacing.Discard="Discard"
79
+Deinterlacing.Retro="Retro"
80
+Deinterlacing.Blend="Blend"
81
+Deinterlacing.Blend2x="Blend 2x"
82
+Deinterlacing.Linear="Linear"
83
+Deinterlacing.Linear2x="Linear 2x"
84
+Deinterlacing.Yadif="Yadif"
85
+Deinterlacing.Yadif2x="Yadif 2x"
86
+Deinterlacing.TopFieldFirst="Önce Üst Alan"
87
+Deinterlacing.BottomFieldFirst="Önce Alt Alan"
88
 
89
 Basic.Main.AddSceneDlg.Title="Sahne Ekle"
90
 Basic.Main.AddSceneDlg.Text="Lütfen sahne adını giriniz"
91
@@ -155,11 +196,16 @@
92
 Basic.PropertiesWindow.Confirm="Kaydedilmeyen değişikler var. Yaptığınız değişikleri kaydetmek istiyor musunuz?"
93
 Basic.PropertiesWindow.NoProperties="Hiçbir özellik mevcut değil"
94
 Basic.PropertiesWindow.AddFiles="Dosya Ekle"
95
+Basic.PropertiesWindow.AddDir="Dizin Ekle"
96
 Basic.PropertiesWindow.AddURL="DosyaYolu/URL Ekle"
97
+Basic.PropertiesWindow.AddEditableListDir="'%1' dizinine ekle"
98
 Basic.PropertiesWindow.AddEditableListFiles="Dosyaları '%1' 'e ekle"
99
 Basic.PropertiesWindow.AddEditableListEntry="Girişi '%1' 'e ekle"
100
 Basic.PropertiesWindow.EditEditableListEntry="'%1' 'den giriş ekle"
101
 
102
+Basic.PropertiesView.FPS.Simple="Basit FPS Değerleri"
103
+Basic.PropertiesView.FPS.Rational="Rasyonel FPS Değerleri"
104
+Basic.PropertiesView.FPS.ValidFPSRanges="Geçerli Kare Aralıkları:"
105
 
106
 Basic.InteractionWindow="Etkileşime geçilen '%1'"
107
 
108
@@ -214,11 +260,15 @@
109
 Basic.Main.Sources="Kaynaklar"
110
 Basic.Main.Connecting="Bağlanıyor..."
111
 Basic.Main.StartRecording="Kaydı Başlat"
112
+Basic.Main.StartReplayBuffer="Tekrar Oynatma Arabelleğini Başlat"
113
 Basic.Main.StartStreaming="Yayını Başlat"
114
 Basic.Main.StopRecording="Kaydı Durdur"
115
 Basic.Main.StoppingRecording="Kayıt Durduruluyor..."
116
+Basic.Main.StopReplayBuffer="Tekrar Oynatma Arabelleğini Durdur"
117
+Basic.Main.StoppingReplayBuffer="Tekrar Oynatma Arabelleği Durduruluyor..."
118
 Basic.Main.StopStreaming="Yayını Durdur"
119
 Basic.Main.StoppingStreaming="Canlı Yayın Durduruluyor..."
120
+Basic.Main.ForceStopStreaming="Yayını Durdur (gecikmeyi yoksay)"
121
 
122
 Basic.MainMenu.File="&Dosya"
123
 Basic.MainMenu.File.Export="Dışa Aktar"
124
@@ -228,6 +278,7 @@
125
 Basic.MainMenu.File.Settings="&Ayarlar"
126
 Basic.MainMenu.File.ShowSettingsFolder="Ayarlar Dosyasını Göster"
127
 Basic.MainMenu.File.ShowProfileFolder="Profil Dosyasını Göster"
128
+Basic.MainMenu.AlwaysOnTop="&Her Zaman Üstte"
129
 Basic.MainMenu.File.Exit="Ç&ıkış"
130
 
131
 Basic.MainMenu.Edit="&Düzenle"
132
@@ -235,8 +286,15 @@
133
 Basic.MainMenu.Edit.Redo="&Tekrar Yap"
134
 Basic.MainMenu.Edit.UndoAction="&$1 Geri al"
135
 Basic.MainMenu.Edit.RedoAction="&$1 Yinele"
136
+Basic.MainMenu.Edit.LockPreview="&Önizlemeyi Kilitle"
137
+Basic.MainMenu.Edit.Scale="Ölçekleme &Önizleme"
138
+Basic.MainMenu.Edit.Scale.Window="Pencereye Ölçekle"
139
+Basic.MainMenu.Edit.Scale.Canvas="Tuval (%1x%2)"
140
+Basic.MainMenu.Edit.Scale.Output="Çıktı (%1x%2)"
141
 Basic.MainMenu.Edit.Transform="&Dönüştür"
142
 Basic.MainMenu.Edit.Transform.EditTransform="&Dönüştürmeyi Düzenle..."
143
+Basic.MainMenu.Edit.Transform.CopyTransform="Dönüştürmeyi Kopyala"
144
+Basic.MainMenu.Edit.Transform.PasteTransform="Dönüştürmeyi Yapıştır"
145
 Basic.MainMenu.Edit.Transform.ResetTransform="&Dönüştürmeyi Sıfırla"
146
 Basic.MainMenu.Edit.Transform.Rotate90CW="90 derece saat yönüne döndür"
147
 Basic.MainMenu.Edit.Transform.Rotate90CCW="90 derece saatin tersi yönüne döndür"
148
@@ -253,10 +311,22 @@
149
 Basic.MainMenu.Edit.Order.MoveToBottom="En &Alta Taşı"
150
 Basic.MainMenu.Edit.AdvAudio="&Gelişmiş Ses Özellikleri"
151
 
152
+Basic.MainMenu.View="&Görünüm"
153
+Basic.MainMenu.View.Toolbars="&Araç Çubukları"
154
+Basic.MainMenu.View.Toolbars.Listboxes="&Liste Kutuları"
155
+Basic.MainMenu.View.SceneTransitions="S&ahne Geçişleri"
156
+Basic.MainMenu.View.StatusBar="&Durum Çubuğu"
157
 
158
 Basic.MainMenu.SceneCollection="&Sahne Koleksiyonu"
159
 Basic.MainMenu.Profile="&Profil"
160
+Basic.MainMenu.Profile.Import="Profili İçe Aktar"
161
+Basic.MainMenu.Profile.Export="Profili Dışa Aktar"
162
+Basic.MainMenu.SceneCollection.Import="Sahne Koleksiyonunu İçe Aktar"
163
+Basic.MainMenu.SceneCollection.Export="Sahne Koleksiyonunu Dışa Aktar"
164
+Basic.MainMenu.Profile.Exists="Profil zaten var"
165
+Basic.MainMenu.SceneCollection.Exists="Sahne koleksiyonu zaten var"
166
 
167
+Basic.MainMenu.Tools="&Araçlar"
168
 
169
 Basic.MainMenu.Help="&Yardım"
170
 Basic.MainMenu.Help.Website="&Siteyi Ziyaret Et"
171
@@ -274,6 +344,19 @@
172
 Basic.Settings.General="Genel"
173
 Basic.Settings.General.Theme="Tema"
174
 Basic.Settings.General.Language="Dil"
175
+Basic.Settings.General.WarnBeforeStartingStream="Yayın başlatırken onay iletişim kutusunu göster"
176
+Basic.Settings.General.WarnBeforeStoppingStream="Yayın durduğunda onay iletişim kutusunu göster"
177
+Basic.Settings.General.HideProjectorCursor="Projektörler üzerinde imleci gizle"
178
+Basic.Settings.General.ProjectorAlwaysOnTop="Projektörleri her zaman üstte tut"
179
+Basic.Settings.General.Snapping="Kaynak Hizalama"
180
+Basic.Settings.General.ScreenSnapping="Kaynakları ekranın kenarına yasla"
181
+Basic.Settings.General.CenterSnapping="Kaynakları dikey ve yatay merkeze yasla"
182
+Basic.Settings.General.SourceSnapping="Kaynakları diğer kaynaklara yasla"
183
+Basic.Settings.General.SnapDistance="Yaslama Hassasiyeti"
184
+Basic.Settings.General.RecordWhenStreaming="Yayın sırasında otomatik olarak kayıt yap"
185
+Basic.Settings.General.KeepRecordingWhenStreamStops="Yayın durduğunda kaydı tut"
186
+Basic.Settings.General.SysTrayEnabled="Sistem tepsisi simgesini etkinleştir"
187
+Basic.Settings.General.SysTrayWhenStarted="Başladığında sistem tepsisine küçült"
188
 
189
 Basic.Settings.Stream="Yayın"
190
 Basic.Settings.Stream.StreamType="Yayın Türü"
191
@@ -283,10 +366,18 @@
192
 Basic.Settings.Output.Encoder="Kodlayıcı"
193
 Basic.Settings.Output.SelectDirectory="Kayıt Dizinini Seçin"
194
 Basic.Settings.Output.SelectFile="Kayıt Dosyasını Seçin"
195
+Basic.Settings.Output.EnforceBitrate="Yayın hizmetini bit hızı sınırlarına zorla"
196
 Basic.Settings.Output.Mode="Çıkış modu"
197
 Basic.Settings.Output.Mode.Simple="Basit"
198
 Basic.Settings.Output.Mode.Adv="Gelişmiş"
199
 Basic.Settings.Output.Mode.FFmpeg="FFmpeg Çıkışı"
200
+Basic.Settings.Output.UseReplayBuffer="Tekrar Oynatma Arabelleğini Etkinleştir"
201
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Maksimum Yeniden Oynatma Süresi (Seconds)"
202
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Maksimum Bellek (Megabayt)"
203
+Basic.Settings.Output.ReplayBuffer.Estimate="Tahmini bellek kullanımı: %1 MB"
204
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Bellek kullanımını tahmin edemezsin. Lütfen maksimum bellek sınırını ayarlayın."
205
+Basic.Settings.Output.ReplayBuffer.Prefix="Tekrar Oynatma Arabelleği Dosya Adı Öneki"
206
+Basic.Settings.Output.ReplayBuffer.Suffix="Suffix"
207
 Basic.Settings.Output.Simple.SavePath="Kayıt Yolu"
208
 Basic.Settings.Output.Simple.RecordingQuality="Kayıt Kalitesi"
209
 Basic.Settings.Output.Simple.RecordingQuality.Stream="Canlı Yayın ile Aynı"
210
@@ -296,31 +387,38 @@
211
 Basic.Settings.Output.Simple.Warn.Lossless.Msg="Kayıpsız kalitede kullanmak istediğinizden emin misiniz?"
212
 Basic.Settings.Output.Simple.Warn.Lossless.Title="Kayıpsız kalite uyarısı!"
213
 Basic.Settings.Output.Simple.Encoder.Software="Yazılım (x264)"
214
+Basic.Settings.Output.Simple.Encoder.Hardware.QSV="Donanım (QSV)"
215
+Basic.Settings.Output.Simple.Encoder.Hardware.AMD="Donanım (AMD)"
216
+Basic.Settings.Output.Simple.Encoder.Hardware.NVENC="Donanım (NVENC)"
217
 Basic.Settings.Output.Simple.Encoder.SoftwareLowCPU="Yazılım (x264 düşük CPU kullanım önayarı, dosya boyutunu artırır)"
218
-Basic.Settings.Output.VideoBitrate="Video Bithızı"
219
-Basic.Settings.Output.AudioBitrate="Ses Bithızı"
220
+Basic.Settings.Output.VideoBitrate="Video Bit Hızı"
221
+Basic.Settings.Output.AudioBitrate="Ses Bit Hızı"
222
 Basic.Settings.Output.Reconnect="Otomatik Yeniden Bağlan"
223
 Basic.Settings.Output.RetryDelay="Yeniden Deneme Gecikmesi (saniye)"
224
 Basic.Settings.Output.MaxRetries="En fazla yeniden deneme sayısı"
225
 Basic.Settings.Output.Advanced="Gelişmiş Kodlayıcı Ayarlarını Etkinleştir"
226
 Basic.Settings.Output.EncoderPreset="Kodlayıcı Önayarı (yüksek = daha az İŞLEMCİ)"
227
 Basic.Settings.Output.CustomEncoderSettings="Özel Kodlayıcı Ayarları"
228
+Basic.Settings.Output.CustomMuxerSettings="Özel Muxer Ayarları"
229
 Basic.Settings.Output.NoSpaceFileName="Dosya ismini boşluk olmadan oluştur"
230
 
231
 Basic.Settings.Output.Adv.Rescale="Çıkışı Yeniden Ölçeklendir"
232
 Basic.Settings.Output.Adv.AudioTrack="Ses Parçası"
233
 Basic.Settings.Output.Adv.Streaming="Yayın"
234
-Basic.Settings.Output.Adv.ApplyServiceSettings="Gerçek zamanlı ayayın hizmeti kodlayıcı ayarlarını zorla"
235
+Basic.Settings.Output.Adv.ApplyServiceSettings="Yayın hizmetini kodlayıcı ayarlarına zorla"
236
 Basic.Settings.Output.Adv.Audio.Track1="Parça 1"
237
 Basic.Settings.Output.Adv.Audio.Track2="Ses İzi 2"
238
 Basic.Settings.Output.Adv.Audio.Track3="Ses İzi 3"
239
 Basic.Settings.Output.Adv.Audio.Track4="Ses İzi 4"
240
+Basic.Settings.Output.Adv.Audio.Track5="Parça 5"
241
+Basic.Settings.Output.Adv.Audio.Track6="Parça 6"
242
 
243
 Basic.Settings.Output.Adv.Recording="Kayıt"
244
 Basic.Settings.Output.Adv.Recording.Type="Tür"
245
 Basic.Settings.Output.Adv.Recording.Type.Standard="Standart"
246
 Basic.Settings.Output.Adv.Recording.Type.FFmpegOutput="Özel Çıkış (FFmpeg)"
247
 Basic.Settings.Output.Adv.Recording.UseStreamEncoder="(Yayın kodlayıcı kullan)"
248
+Basic.Settings.Output.Adv.Recording.Filename="Dosya Adı Biçimi"
249
 Basic.Settings.Output.Adv.Recording.OverwriteIfExists="Dosya varsa üzerine yaz"
250
 Basic.Settings.Output.Adv.FFmpeg.Type="FFmpeg Çıkış Türü"
251
 Basic.Settings.Output.Adv.FFmpeg.Type.URL="URL'ye Çıkış"
252
@@ -378,9 +476,11 @@
253
 Basic.Settings.Audio.UnknownAudioDevice="[Cihaz bağlı yada kullanılabilir değil]"
254
 
255
 Basic.Settings.Advanced="Gelişmiş"
256
+Basic.Settings.Advanced.General.ProcessPriority="İşlem Önceliği"
257
 Basic.Settings.Advanced.General.ProcessPriority.High="Yüksek"
258
 Basic.Settings.Advanced.General.ProcessPriority.AboveNormal="Normalin Üstünde"
259
 Basic.Settings.Advanced.General.ProcessPriority.Normal="Normal"
260
+Basic.Settings.Advanced.General.ProcessPriority.Idle="Boşta"
261
 Basic.Settings.Advanced.FormatWarning="Uyarı: NV12 dışındaki renk biçimleri esas olarak kayıt için tasarlanmıştır ve yayın anında kullanma önerilmez. Yayın nedeni ile renk biçimini dönüştürme çok fazla İŞLEMCİ kullanımına sebep olabilir."
262
 Basic.Settings.Advanced.Audio.BufferingTime="Ses Ön Bellekleme Süresi"
263
 Basic.Settings.Advanced.Video.ColorFormat="Renk Biçimi"
264
@@ -392,26 +492,30 @@
265
 Basic.Settings.Advanced.StreamDelay.Duration="Süre (saniye)"
266
 Basic.Settings.Advanced.StreamDelay.Preserve="Tatbik ederken kesim noktasını (gecikme artışı) koru"
267
 Basic.Settings.Advanced.StreamDelay.MemoryUsage="Tahmini Bellek Kullanımı: %1 MB"
268
+Basic.Settings.Advanced.Network="Ağ"
269
+Basic.Settings.Advanced.Network.BindToIP="IP Bağla"
270
 
271
 Basic.AdvAudio="Gelişmiş Ses Özellikleri"
272
 Basic.AdvAudio.Name="İsim"
273
 Basic.AdvAudio.Volume="Ses Düzeyi (%)"
274
 Basic.AdvAudio.Mono="Mono Karıştırmayı Azalt"
275
+Basic.AdvAudio.Panning="Kaydırma"
276
+Basic.AdvAudio.SyncOffset="Eşitleme Uzaklığı (ms)"
277
 Basic.AdvAudio.AudioTracks="Parçalar"
278
 
279
 Basic.Settings.Hotkeys="Kısayollar"
280
 
281
-Basic.Hotkeys.StartStreaming="Yayını Başlat"
282
-Basic.Hotkeys.StopStreaming="Yayını Durdur"
283
-Basic.Hotkeys.StartRecording="Kaydı Başlat"
284
-Basic.Hotkeys.StopRecording="Kaydı Durdur"
285
 Basic.Hotkeys.SelectScene="Sahneye geçiş yap"
286
 
287
+Basic.SystemTray.Show="Göster"
288
+Basic.SystemTray.Hide="Gizle"
289
 
290
+Basic.SystemTray.Message.Reconnecting="Bağlantı kesildi.  Yeniden bağlanılıyor..."
291
 
292
 Hotkeys.Insert="Ekle"
293
 Hotkeys.Delete="Sil"
294
 Hotkeys.Home="Ana Sayfa"
295
+Hotkeys.End="End"
296
 Hotkeys.PageUp="Page Up"
297
 Hotkeys.PageDown="Page Down"
298
 Hotkeys.NumLock="Num Lock"
299
@@ -420,6 +524,7 @@
300
 Hotkeys.Backspace="Backspace"
301
 Hotkeys.Tab="Tab"
302
 Hotkeys.Print="Yazdır"
303
+Hotkeys.Pause="Duraklat"
304
 Hotkeys.Left="Sol"
305
 Hotkeys.Right="Sağ"
306
 Hotkeys.Up="Yukarı"
307
@@ -429,6 +534,11 @@
308
 Hotkeys.Menu="Menü"
309
 Hotkeys.Space="Boşluk"
310
 Hotkeys.NumpadNum="Numpad %1"
311
+Hotkeys.NumpadMultiply="Numpad *"
312
+Hotkeys.NumpadDivide="Numpad /"
313
+Hotkeys.NumpadAdd="Numpad Ekle"
314
+Hotkeys.NumpadSubtract="Numpad -"
315
+Hotkeys.NumpadDecimal="Numpad ,"
316
 Hotkeys.AppleKeypadNum="%1 (Tuş takımı)"
317
 Hotkeys.AppleKeypadMultiply="* (Tuş takımı)"
318
 Hotkeys.AppleKeypadDivide="/ (Tuş takımı)"
319
obs-studio-0.16.6.tar.xz/UI/data/locale/uk-UA.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/uk-UA.ini Changed
59
 
1
@@ -53,6 +53,9 @@
2
 Minutes="Хвилин"
3
 Seconds="Секунд"
4
 Deprecated="Припинено підтримку"
5
+ReplayBuffer="Буфер Повторів"
6
+Import="Імпорт"
7
+Export="Експорт"
8
 
9
 QuickTransitions.SwapScenes="Поміняти місцями сцени Перегляд/Вивід після Відео-переходу"
10
 QuickTransitions.SwapScenesTT="Міняє місцями сцени Перегляд та Вивід після закінчення Відео-переходу (якщо сцена Вивід ще існує).\nЗміни внесені до обох сцен залишаються."
11
@@ -107,6 +110,8 @@
12
 Output.RecordNoSpace.Msg="На диску недостатньо простору для запису."
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
@@ -262,9 +267,12 @@
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
@@ -362,6 +370,14 @@
34
 Basic.Settings.Output.Mode.Simple="Простий"
35
 Basic.Settings.Output.Mode.Adv="Розширений"
36
 Basic.Settings.Output.Mode.FFmpeg="Вивід FFmpeg"
37
+Basic.Settings.Output.UseReplayBuffer="Увімкнути Буфер Повторів"
38
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Максимальна тривалість Повтору (у секундах)"
39
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Максимальний об'єм пам'яті (у мегабайтах)"
40
+Basic.Settings.Output.ReplayBuffer.Estimate="Буде використано пам'яті: %1 МБ"
41
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Не вдалося оцінити об'єм використання пам'яті. Будь ласка, встановіть максимальний об'єм пам'яті для Буферу Повторів вручну."
42
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Примітка: переконайтеся, що встановили гарячу клавішу для Буферу Повторів в розділі гарячі клавіші)"
43
+Basic.Settings.Output.ReplayBuffer.Prefix="Буфер Повторів, Ім'я файлу, Префікс"
44
+Basic.Settings.Output.ReplayBuffer.Suffix="Суфікс"
45
 Basic.Settings.Output.Simple.SavePath="Шлях до запису"
46
 Basic.Settings.Output.Simple.RecordingQuality="Якість запису"
47
 Basic.Settings.Output.Simple.RecordingQuality.Stream="Так само як трансляція"
48
@@ -497,10 +513,6 @@
49
 Basic.Settings.Hotkeys="Гарячі клавіші"
50
 Basic.Settings.Hotkeys.Pair="Однакові комбінації клавіш задані до '%1' діють як перемикач"
51
 
52
-Basic.Hotkeys.StartStreaming="Почати трансляцію"
53
-Basic.Hotkeys.StopStreaming="Закінчити трансляцію"
54
-Basic.Hotkeys.StartRecording="Почати запис"
55
-Basic.Hotkeys.StopRecording="Зупинити запис"
56
 Basic.Hotkeys.SelectScene="Перейти до сцени"
57
 
58
 Basic.SystemTray.Show="Показати"
59
obs-studio-0.16.6.tar.xz/UI/data/locale/vi-VN.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/vi-VN.ini Changed
109
 
1
@@ -253,56 +253,56 @@
2
 Basic.Main.Scenes="Cảnh"
3
 Basic.Main.Sources="Nguồn"
4
 Basic.Main.Connecting="Đang kết nối..."
5
-Basic.Main.StartRecording="Bắt đầu ghi âm"
6
+Basic.Main.StartRecording="Bắt đầu ghi"
7
 Basic.Main.StartStreaming="Bắt đầu Streaming"
8
-Basic.Main.StopRecording="Dừng ghi âm"
9
+Basic.Main.StopRecording="Dừng ghi"
10
 Basic.Main.StoppingRecording="Dừng ghi video..."
11
 Basic.Main.StopStreaming="Ngừng Streaming"
12
 Basic.Main.StoppingStreaming="Dừng stream..."
13
 Basic.Main.ForceStopStreaming="Ngừng Streaming (huỷ chậm trễ)"
14
 
15
 Basic.MainMenu.File="&Tập tin"
16
-Basic.MainMenu.File.Export="&Xuất khẩu"
17
-Basic.MainMenu.File.Import="&Nhập khẩu"
18
-Basic.MainMenu.File.ShowRecordings="Bản ghi âm & Hiển thị"
19
-Basic.MainMenu.File.Remux="Re & mux bản ghi âm"
20
+Basic.MainMenu.File.Export="&Xuất"
21
+Basic.MainMenu.File.Import="&Nhập"
22
+Basic.MainMenu.File.ShowRecordings="Hiển thị &Bản ghi"
23
+Basic.MainMenu.File.Remux="Re&mux bản ghi"
24
 Basic.MainMenu.File.Settings="&Cài đặt"
25
-Basic.MainMenu.File.ShowSettingsFolder="Hiển thị cài đặt thư mục"
26
+Basic.MainMenu.File.ShowSettingsFolder="Hiển thị thư mục cài đặt"
27
 Basic.MainMenu.File.ShowProfileFolder="Hiển thị thư mục hồ sơ"
28
 Basic.MainMenu.AlwaysOnTop="&Luôn trên đầu trang"
29
 Basic.MainMenu.File.Exit="&Thoát"
30
 
31
-Basic.MainMenu.Edit="& Chỉnh sửa"
32
-Basic.MainMenu.Edit.Undo="& Hoàn tác"
33
-Basic.MainMenu.Edit.Redo="& Làm lại"
34
-Basic.MainMenu.Edit.UndoAction="& Hoàn tác $1"
35
-Basic.MainMenu.Edit.RedoAction="& Làm lại $1"
36
+Basic.MainMenu.Edit="&Chỉnh sửa"
37
+Basic.MainMenu.Edit.Undo="&Hoàn tác"
38
+Basic.MainMenu.Edit.Redo="&Làm lại"
39
+Basic.MainMenu.Edit.UndoAction="&Hoàn tác $1"
40
+Basic.MainMenu.Edit.RedoAction="&Làm lại $1"
41
 Basic.MainMenu.Edit.LockPreview="&Khóa xem trước"
42
-Basic.MainMenu.Edit.Transform="Biến đổi"
43
-Basic.MainMenu.Edit.Transform.EditTransform="& Chỉnh sửa biến đổi..."
44
-Basic.MainMenu.Edit.Transform.ResetTransform="& Đặt lại biến đổi"
45
+Basic.MainMenu.Edit.Transform="&Biến đổi"
46
+Basic.MainMenu.Edit.Transform.EditTransform="&Chỉnh sửa biến đổi..."
47
+Basic.MainMenu.Edit.Transform.ResetTransform="&Đặt lại biến đổi"
48
 Basic.MainMenu.Edit.Transform.Rotate90CW="Xoay 90 độ bên phải"
49
 Basic.MainMenu.Edit.Transform.Rotate90CCW="Xoay 90 độ bên trái"
50
 Basic.MainMenu.Edit.Transform.Rotate180="Xoay 180 độ"
51
-Basic.MainMenu.Edit.Transform.FlipHorizontal="Flip & ngang"
52
-Basic.MainMenu.Edit.Transform.FlipVertical="Flip & dọc"
53
-Basic.MainMenu.Edit.Transform.FitToScreen="Phù hợp với màn hình"
54
-Basic.MainMenu.Edit.Transform.StretchToScreen="& Căng để màn hình"
55
+Basic.MainMenu.Edit.Transform.FlipHorizontal="Lật &Ngang"
56
+Basic.MainMenu.Edit.Transform.FlipVertical="Lật &Dọc"
57
+Basic.MainMenu.Edit.Transform.FitToScreen="&Vừa với màn hình"
58
+Basic.MainMenu.Edit.Transform.StretchToScreen="&Giãn ra để lấp đầy m.hình"
59
 Basic.MainMenu.Edit.Transform.CenterToScreen="& Trung tâm màn hình"
60
-Basic.MainMenu.Edit.Order="& Đặt hàng"
61
-Basic.MainMenu.Edit.Order.MoveUp="Chuyển Lên"
62
-Basic.MainMenu.Edit.Order.MoveDown="Chuyển xuống"
63
-Basic.MainMenu.Edit.Order.MoveToTop="Chuyển đến đầu trang"
64
-Basic.MainMenu.Edit.Order.MoveToBottom="Chuyển đến dưới cùng"
65
-Basic.MainMenu.Edit.AdvAudio="Thuộc tính âm thanh nâng cao"
66
+Basic.MainMenu.Edit.Order="&Đặt"
67
+Basic.MainMenu.Edit.Order.MoveUp="Chuyển &Lên"
68
+Basic.MainMenu.Edit.Order.MoveDown="Chuyển &Xuống"
69
+Basic.MainMenu.Edit.Order.MoveToTop="Chuyển đến &Đầu"
70
+Basic.MainMenu.Edit.Order.MoveToBottom="Chuyển xuống &Dưới"
71
+Basic.MainMenu.Edit.AdvAudio="Các thuộc tính âm thanh nâng cao"
72
 
73
 Basic.MainMenu.View="&Hiển thị"
74
 Basic.MainMenu.View.Toolbars="&Thanh công cụ"
75
 Basic.MainMenu.View.Toolbars.Listboxes="&Listboxes"
76
 Basic.MainMenu.View.StatusBar="&Thanh trạng thái"
77
 
78
-Basic.MainMenu.SceneCollection="& Cảnh bộ sưu tập"
79
-Basic.MainMenu.Profile="& Hồ sơ"
80
+Basic.MainMenu.SceneCollection="& Bộ sưu tập cảnh"
81
+Basic.MainMenu.Profile="&Hồ sơ"
82
 
83
 Basic.MainMenu.Tools="&Công cụ"
84
 
85
@@ -431,9 +431,9 @@
86
 Basic.Settings.Audio.AuxDevice="Thiết bị âm thanh mic/phụ trợ"
87
 Basic.Settings.Audio.AuxDevice2="Thiết bị âm thanh mic/phụ trợ 2"
88
 Basic.Settings.Audio.AuxDevice3="Thiết bị âm thanh mic/phụ trợ 3"
89
-Basic.Settings.Audio.EnablePushToMute="Sử đẩy để tắt tiếng"
90
-Basic.Settings.Audio.PushToMuteDelay="Sự chậm trễ đẩy để tắt tiếng"
91
-Basic.Settings.Audio.EnablePushToTalk="Sử Push-to-talk"
92
+Basic.Settings.Audio.EnablePushToMute="Bật bấm để tắt tiếng"
93
+Basic.Settings.Audio.PushToMuteDelay="Bấm để tắt tiếng trễ"
94
+Basic.Settings.Audio.EnablePushToTalk="Bật bắm để nói"
95
 Basic.Settings.Audio.PushToTalkDelay="Bấm để nói trễ"
96
 Basic.Settings.Audio.UnknownAudioDevice="[Thiết bị không được kết nối hoặc không sẵn dùng]"
97
 
98
@@ -468,10 +468,6 @@
99
 Basic.Settings.Hotkeys="Phím nóng"
100
 Basic.Settings.Hotkeys.Pair="Tổ hợp phím được chia sẻ với '%1' hành động như chuyển"
101
 
102
-Basic.Hotkeys.StartStreaming="Bắt đầu Streaming"
103
-Basic.Hotkeys.StopStreaming="Ngừng Streaming"
104
-Basic.Hotkeys.StartRecording="Bắt đầu ghi âm"
105
-Basic.Hotkeys.StopRecording="Dừng ghi âm"
106
 Basic.Hotkeys.SelectScene="Chuyển cảnh"
107
 
108
 Basic.SystemTray.Show="Hiện"
109
obs-studio-0.16.6.tar.xz/UI/data/locale/zh-CN.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/zh-CN.ini Changed
90
 
1
@@ -53,6 +53,9 @@
2
 Minutes="分钟"
3
 Seconds="秒"
4
 Deprecated="不推荐使用"
5
+ReplayBuffer="重拨缓存"
6
+Import="导入"
7
+Export="导出"
8
 
9
 QuickTransitions.SwapScenes="在过渡动画后交换预览/输出场景"
10
 QuickTransitions.SwapScenesTT="在过渡后,交换预览和输出场景(如果输出的原始场景仍然存在). \n 这个不会撤消任何可能对输出的原始场景的更改."
11
@@ -107,6 +110,8 @@
12
 Output.RecordNoSpace.Msg="没有足够磁盘空间来继续录像."
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
@@ -262,9 +267,12 @@
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
@@ -292,6 +300,8 @@
34
 Basic.MainMenu.Edit.Scale.Output="输出 (%1x%2)"
35
 Basic.MainMenu.Edit.Transform="变换 (&T)"
36
 Basic.MainMenu.Edit.Transform.EditTransform="编辑变换 (&E)"
37
+Basic.MainMenu.Edit.Transform.CopyTransform="复制变换"
38
+Basic.MainMenu.Edit.Transform.PasteTransform="粘贴变换"
39
 Basic.MainMenu.Edit.Transform.ResetTransform="重置变换 (&R)"
40
 Basic.MainMenu.Edit.Transform.Rotate90CW="顺时针旋转 90 度(&9)"
41
 Basic.MainMenu.Edit.Transform.Rotate90CCW="逆时针旋转 90 度(&D)"
42
@@ -316,6 +326,12 @@
43
 
44
 Basic.MainMenu.SceneCollection="场景集合 (&S)"
45
 Basic.MainMenu.Profile="配置文件 (&P)"
46
+Basic.MainMenu.Profile.Import="导入配置文件"
47
+Basic.MainMenu.Profile.Export="导出配置文件"
48
+Basic.MainMenu.SceneCollection.Import="导入场景集合"
49
+Basic.MainMenu.SceneCollection.Export="导出场景集合"
50
+Basic.MainMenu.Profile.Exists="配置文件已存在"
51
+Basic.MainMenu.SceneCollection.Exists="场景机会已存在"
52
 
53
 Basic.MainMenu.Tools="工具 (&T)"
54
 
55
@@ -362,6 +378,14 @@
56
 Basic.Settings.Output.Mode.Simple="简单"
57
 Basic.Settings.Output.Mode.Adv="高级"
58
 Basic.Settings.Output.Mode.FFmpeg="FFmpeg 输出"
59
+Basic.Settings.Output.UseReplayBuffer="启用回放缓存"
60
+Basic.Settings.Output.ReplayBuffer.SecondsMax="最大回放时间(秒)"
61
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="最大内存(Mb)"
62
+Basic.Settings.Output.ReplayBuffer.Estimate="估计内存使用率: %1 MB"
63
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="无法估计内存使用率. 请设置最大内存限制."
64
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(注意: 确保在快捷键部分设置一个回放缓冲区的快捷键)"
65
+Basic.Settings.Output.ReplayBuffer.Prefix="回放缓存文件名前缀"
66
+Basic.Settings.Output.ReplayBuffer.Suffix="后缀"
67
 Basic.Settings.Output.Simple.SavePath="录像路径"
68
 Basic.Settings.Output.Simple.RecordingQuality="录像质量"
69
 Basic.Settings.Output.Simple.RecordingQuality.Stream="与流相同"
70
@@ -399,6 +423,8 @@
71
 Basic.Settings.Output.Adv.Audio.Track2="轨道 2"
72
 Basic.Settings.Output.Adv.Audio.Track3="轨道 3"
73
 Basic.Settings.Output.Adv.Audio.Track4="轨道 4"
74
+Basic.Settings.Output.Adv.Audio.Track5="轨道 5"
75
+Basic.Settings.Output.Adv.Audio.Track6="轨道 6"
76
 
77
 Basic.Settings.Output.Adv.Recording="录像"
78
 Basic.Settings.Output.Adv.Recording.Type="类型"
79
@@ -497,10 +523,6 @@
80
 Basic.Settings.Hotkeys="热键"
81
 Basic.Settings.Hotkeys.Pair="作为切换的键组合与 '%1' 共享"
82
 
83
-Basic.Hotkeys.StartStreaming="开始串流"
84
-Basic.Hotkeys.StopStreaming="停止串流"
85
-Basic.Hotkeys.StartRecording="开始录像"
86
-Basic.Hotkeys.StopRecording="停止录像"
87
 Basic.Hotkeys.SelectScene="切换到场景"
88
 
89
 Basic.SystemTray.Show="显示"
90
obs-studio-0.16.6.tar.xz/UI/data/locale/zh-TW.ini -> obs-studio-0.17.0.tar.xz/UI/data/locale/zh-TW.ini Changed
90
 
1
@@ -53,6 +53,9 @@
2
 Minutes="分鐘"
3
 Seconds="秒"
4
 Deprecated="不再維護"
5
+ReplayBuffer="重播緩衝"
6
+Import="匯入"
7
+Export="匯出"
8
 
9
 QuickTransitions.SwapScenes="轉場後交換預覽/輸出場景"
10
 QuickTransitions.SwapScenesTT="(如果輸出的原始場景仍然存在) 轉場後交換預覽和輸出場景。\n這並不會復原任何對輸出原始場景所作的改動。"
11
@@ -107,6 +110,8 @@
12
 Output.RecordNoSpace.Msg="沒有足夠的空間存放錄製影片"
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
@@ -262,9 +267,12 @@
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
@@ -292,6 +300,8 @@
34
 Basic.MainMenu.Edit.Scale.Output="輸出 (%1x%2)"
35
 Basic.MainMenu.Edit.Transform="變型 (&T)"
36
 Basic.MainMenu.Edit.Transform.EditTransform="編輯變型設定…… (&E)"
37
+Basic.MainMenu.Edit.Transform.CopyTransform="複製變型"
38
+Basic.MainMenu.Edit.Transform.PasteTransform="貼上變型"
39
 Basic.MainMenu.Edit.Transform.ResetTransform="重設變型設定 (&R)"
40
 Basic.MainMenu.Edit.Transform.Rotate90CW="順時針旋轉 90°"
41
 Basic.MainMenu.Edit.Transform.Rotate90CCW="逆時針旋轉 90°"
42
@@ -316,6 +326,12 @@
43
 
44
 Basic.MainMenu.SceneCollection="場景群組 (&S)"
45
 Basic.MainMenu.Profile="設定檔 (&P)"
46
+Basic.MainMenu.Profile.Import="匯入設定檔"
47
+Basic.MainMenu.Profile.Export="匯出設定檔"
48
+Basic.MainMenu.SceneCollection.Import="匯入場景群組"
49
+Basic.MainMenu.SceneCollection.Export="匯出場景群組"
50
+Basic.MainMenu.Profile.Exists="已有該設定檔"
51
+Basic.MainMenu.SceneCollection.Exists="已有該場景群組"
52
 
53
 Basic.MainMenu.Tools="工具(&T)"
54
 
55
@@ -362,6 +378,14 @@
56
 Basic.Settings.Output.Mode.Simple="簡易"
57
 Basic.Settings.Output.Mode.Adv="進階"
58
 Basic.Settings.Output.Mode.FFmpeg="FFmpeg 輸出"
59
+Basic.Settings.Output.UseReplayBuffer="啟用重播緩衝"
60
+Basic.Settings.Output.ReplayBuffer.SecondsMax="最大重播時間(秒)"
61
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="最大記憶體使用量(MB)"
62
+Basic.Settings.Output.ReplayBuffer.Estimate="估計記憶體使用量︰ %1 MB"
63
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="無法預估記憶體使用量。請設定最大記憶體使用量。"
64
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(注意:請確定在熱鍵區有為重播緩衝設定熱鍵)"
65
+Basic.Settings.Output.ReplayBuffer.Prefix="重播緩衝檔案名稱前綴"
66
+Basic.Settings.Output.ReplayBuffer.Suffix="後綴"
67
 Basic.Settings.Output.Simple.SavePath="錄影路徑"
68
 Basic.Settings.Output.Simple.RecordingQuality="錄影畫質"
69
 Basic.Settings.Output.Simple.RecordingQuality.Stream="與串流同等畫質"
70
@@ -399,6 +423,8 @@
71
 Basic.Settings.Output.Adv.Audio.Track2="音軌 2"
72
 Basic.Settings.Output.Adv.Audio.Track3="音軌 3"
73
 Basic.Settings.Output.Adv.Audio.Track4="音軌 4"
74
+Basic.Settings.Output.Adv.Audio.Track5="音軌 5"
75
+Basic.Settings.Output.Adv.Audio.Track6="音軌 6"
76
 
77
 Basic.Settings.Output.Adv.Recording="錄影"
78
 Basic.Settings.Output.Adv.Recording.Type="類型"
79
@@ -497,10 +523,6 @@
80
 Basic.Settings.Hotkeys="快捷鍵"
81
 Basic.Settings.Hotkeys.Pair="按鍵組合與'%1'共用作為切換鍵"
82
 
83
-Basic.Hotkeys.StartStreaming="開始串流"
84
-Basic.Hotkeys.StopStreaming="停止串流"
85
-Basic.Hotkeys.StartRecording="開始錄影"
86
-Basic.Hotkeys.StopRecording="停止錄影"
87
 Basic.Hotkeys.SelectScene="切換到場景"
88
 
89
 Basic.SystemTray.Show="顯示"
90
obs-studio-0.16.6.tar.xz/UI/forms/OBSBasic.ui -> obs-studio-0.17.0.tar.xz/UI/forms/OBSBasic.ui Changed
82
 
1
@@ -850,6 +850,8 @@
2
       <string>Basic.MainMenu.Edit.Transform</string>
3
      </property>
4
      <addaction name="actionEditTransform"/>
5
+     <addaction name="actionCopyTransform"/>
6
+     <addaction name="actionPasteTransform"/>
7
      <addaction name="actionResetTransform"/>
8
      <addaction name="separator"/>
9
      <addaction name="actionRotate90CW"/>
10
@@ -896,6 +898,8 @@
11
     <addaction name="actionDupProfile"/>
12
     <addaction name="actionRenameProfile"/>
13
     <addaction name="actionRemoveProfile"/>
14
+    <addaction name="actionImportProfile"/>
15
+    <addaction name="actionExportProfile"/>
16
     <addaction name="separator"/>
17
    </widget>
18
    <widget class="QMenu" name="sceneCollectionMenu">
19
@@ -906,6 +910,8 @@
20
     <addaction name="actionDupSceneCollection"/>
21
     <addaction name="actionRenameSceneCollection"/>
22
     <addaction name="actionRemoveSceneCollection"/>
23
+    <addaction name="actionImportSceneCollection"/>
24
+    <addaction name="actionExportSceneCollection"/>
25
     <addaction name="separator"/>
26
    </widget>
27
    <widget class="QMenu" name="viewMenu">
28
@@ -1129,6 +1135,19 @@
29
     <string>Basic.MainMenu.Edit.Transform.EditTransform</string>
30
    </property>
31
   </action>
32
+  <action name="actionCopyTransform">
33
+   <property name="text">
34
+    <string>Basic.MainMenu.Edit.Transform.CopyTransform</string>
35
+   </property>
36
+  </action>
37
+  <action name="actionPasteTransform">
38
+   <property name="enabled">
39
+    <bool>false</bool>
40
+   </property>
41
+   <property name="text">
42
+    <string>Basic.MainMenu.Edit.Transform.PasteTransform</string>
43
+   </property>
44
+  </action>
45
   <action name="actionRotate90CW">
46
    <property name="text">
47
     <string>Basic.MainMenu.Edit.Transform.Rotate90CW</string>
48
@@ -1258,6 +1277,16 @@
49
     <string>Remove</string>
50
    </property>
51
   </action>
52
+  <action name="actionImportSceneCollection">
53
+   <property name="text">
54
+    <string>Import</string>
55
+   </property>
56
+  </action>
57
+  <action name="actionExportSceneCollection">
58
+   <property name="text">
59
+    <string>Export</string>
60
+   </property>
61
+  </action>
62
   <action name="actionNewProfile">
63
    <property name="text">
64
     <string>New</string>
65
@@ -1278,6 +1307,16 @@
66
     <string>Remove</string>
67
    </property>
68
   </action>
69
+  <action name="actionImportProfile">
70
+   <property name="text">
71
+    <string>Import</string>
72
+   </property>
73
+  </action>
74
+  <action name="actionExportProfile">
75
+   <property name="text">
76
+    <string>Export</string>
77
+   </property>
78
+  </action>
79
   <action name="actionShowSettingsFolder">
80
    <property name="text">
81
     <string>Basic.MainMenu.File.ShowSettingsFolder</string>
82
obs-studio-0.16.6.tar.xz/UI/forms/OBSBasicSettings.ui -> obs-studio-0.17.0.tar.xz/UI/forms/OBSBasicSettings.ui Changed
1055
 
1
@@ -7,7 +7,7 @@
2
     <x>0</x>
3
     <y>0</y>
4
     <width>981</width>
5
-    <height>667</height>
6
+    <height>748</height>
7
    </rect>
8
   </property>
9
   <property name="sizePolicy">
10
@@ -722,7 +722,7 @@
11
               </widget>
12
              </item>
13
              <item>
14
-              <widget class="QGroupBox" name="groupBox_9">
15
+              <widget class="QGroupBox" name="simpleRecordingGroupBox">
16
                <property name="sizePolicy">
17
                 <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
18
                  <horstretch>0</horstretch>
19
@@ -739,6 +739,25 @@
20
                 <property name="labelAlignment">
21
                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
22
                 </property>
23
+                <item row="0" column="0">
24
+                 <widget class="QLabel" name="label_18">
25
+                  <property name="minimumSize">
26
+                   <size>
27
+                    <width>170</width>
28
+                    <height>0</height>
29
+                   </size>
30
+                  </property>
31
+                  <property name="text">
32
+                   <string>Basic.Settings.Output.Simple.SavePath</string>
33
+                  </property>
34
+                  <property name="alignment">
35
+                   <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
36
+                  </property>
37
+                  <property name="buddy">
38
+                   <cstring>simpleOutputPath</cstring>
39
+                  </property>
40
+                 </widget>
41
+                </item>
42
                 <item row="0" column="1">
43
                  <layout class="QHBoxLayout" name="horizontalLayout_5">
44
                   <item>
45
@@ -760,32 +779,36 @@
46
                   </item>
47
                  </layout>
48
                 </item>
49
-                <item row="0" column="0">
50
-                 <widget class="QLabel" name="label_18">
51
-                  <property name="minimumSize">
52
-                   <size>
53
-                    <width>170</width>
54
-                    <height>0</height>
55
-                   </size>
56
-                  </property>
57
+                <item row="1" column="1">
58
+                 <widget class="QCheckBox" name="simpleNoSpace">
59
                   <property name="text">
60
-                   <string>Basic.Settings.Output.Simple.SavePath</string>
61
+                   <string>Basic.Settings.Output.NoSpaceFileName</string>
62
                   </property>
63
-                  <property name="alignment">
64
-                   <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
65
+                  <property name="checked">
66
+                   <bool>true</bool>
67
+                  </property>
68
+                 </widget>
69
+                </item>
70
+                <item row="2" column="0">
71
+                 <widget class="QLabel" name="label_26">
72
+                  <property name="text">
73
+                   <string>Basic.Settings.Output.Simple.RecordingQuality</string>
74
                   </property>
75
                   <property name="buddy">
76
-                   <cstring>simpleOutputPath</cstring>
77
+                   <cstring>simpleOutRecQuality</cstring>
78
                   </property>
79
                  </widget>
80
                 </item>
81
-                <item row="1" column="1">
82
-                 <widget class="QCheckBox" name="simpleNoSpace">
83
+                <item row="2" column="1">
84
+                 <widget class="QComboBox" name="simpleOutRecQuality"/>
85
+                </item>
86
+                <item row="3" column="0">
87
+                 <widget class="QLabel" name="simpleOutRecFormatLabel">
88
                   <property name="text">
89
-                   <string>Basic.Settings.Output.NoSpaceFileName</string>
90
+                   <string>Basic.Settings.Output.Format</string>
91
                   </property>
92
-                  <property name="checked">
93
-                   <bool>true</bool>
94
+                  <property name="buddy">
95
+                   <cstring>simpleOutRecFormat</cstring>
96
                   </property>
97
                  </widget>
98
                 </item>
99
@@ -823,54 +846,116 @@
100
                   </item>
101
                  </widget>
102
                 </item>
103
-                <item row="3" column="0">
104
-                 <widget class="QLabel" name="simpleOutRecFormatLabel">
105
+                <item row="4" column="0">
106
+                 <widget class="QLabel" name="simpleOutRecEncoderLabel">
107
                   <property name="text">
108
-                   <string>Basic.Settings.Output.Format</string>
109
+                   <string>Basic.Settings.Output.Encoder</string>
110
                   </property>
111
                   <property name="buddy">
112
-                   <cstring>simpleOutRecFormat</cstring>
113
+                   <cstring>simpleOutRecEncoder</cstring>
114
                   </property>
115
                  </widget>
116
                 </item>
117
-                <item row="2" column="1">
118
-                 <widget class="QComboBox" name="simpleOutRecQuality"/>
119
+                <item row="4" column="1">
120
+                 <widget class="QComboBox" name="simpleOutRecEncoder"/>
121
                 </item>
122
-                <item row="2" column="0">
123
-                 <widget class="QLabel" name="label_26">
124
+                <item row="5" column="0">
125
+                 <widget class="QLabel" name="label_420">
126
                   <property name="text">
127
-                   <string>Basic.Settings.Output.Simple.RecordingQuality</string>
128
+                   <string>Basic.Settings.Output.CustomMuxerSettings</string>
129
                   </property>
130
                   <property name="buddy">
131
-                   <cstring>simpleOutRecQuality</cstring>
132
+                   <cstring>simpleOutMuxCustom</cstring>
133
                   </property>
134
                  </widget>
135
                 </item>
136
-                <item row="4" column="1">
137
-                 <widget class="QComboBox" name="simpleOutRecEncoder"/>
138
+                <item row="5" column="1">
139
+                 <widget class="QLineEdit" name="simpleOutMuxCustom"/>
140
                 </item>
141
-                <item row="4" column="0">
142
-                 <widget class="QLabel" name="simpleOutRecEncoderLabel">
143
+                <item row="6" column="1">
144
+                 <widget class="QCheckBox" name="simpleReplayBuf">
145
                   <property name="text">
146
-                   <string>Basic.Settings.Output.Encoder</string>
147
+                   <string>Basic.Settings.Output.UseReplayBuffer</string>
148
                   </property>
149
-                  <property name="buddy">
150
-                   <cstring>simpleOutRecEncoder</cstring>
151
+                  <property name="checked">
152
+                   <bool>true</bool>
153
                   </property>
154
                  </widget>
155
                 </item>
156
-                <item row="5" column="0">
157
-                 <widget class="QLabel" name="label_420">
158
+               </layout>
159
+              </widget>
160
+             </item>
161
+             <item>
162
+              <widget class="QGroupBox" name="replayBufferGroupBox">
163
+               <property name="title">
164
+                <string>ReplayBuffer</string>
165
+               </property>
166
+               <layout class="QFormLayout" name="formLayout_24">
167
+                <property name="fieldGrowthPolicy">
168
+                 <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
169
+                </property>
170
+                <property name="labelAlignment">
171
+                 <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
172
+                </property>
173
+                <item row="0" column="0">
174
+                 <widget class="QLabel" name="label_35">
175
                   <property name="text">
176
-                   <string>Basic.Settings.Output.CustomMuxerSettings</string>
177
+                   <string>Basic.Settings.Output.ReplayBuffer.SecondsMax</string>
178
                   </property>
179
-                  <property name="buddy">
180
-                   <cstring>simpleOutMuxCustom</cstring>
181
+                 </widget>
182
+                </item>
183
+                <item row="0" column="1">
184
+                 <widget class="QSpinBox" name="simpleRBSecMax">
185
+                  <property name="suffix">
186
+                   <string notr="true"> sec</string>
187
+                  </property>
188
+                  <property name="minimum">
189
+                   <number>5</number>
190
+                  </property>
191
+                  <property name="maximum">
192
+                   <number>21600</number>
193
+                  </property>
194
+                  <property name="value">
195
+                   <number>15</number>
196
                   </property>
197
                  </widget>
198
                 </item>
199
-                <item row="5" column="1">
200
-                 <widget class="QLineEdit" name="simpleOutMuxCustom"/>
201
+                <item row="1" column="0">
202
+                 <widget class="QLabel" name="simpleRBMegsMaxLabel">
203
+                  <property name="text">
204
+                   <string>Basic.Settings.Output.ReplayBuffer.MegabytesMax</string>
205
+                  </property>
206
+                 </widget>
207
+                </item>
208
+                <item row="1" column="1">
209
+                 <widget class="QSpinBox" name="simpleRBMegsMax">
210
+                  <property name="suffix">
211
+                   <string notr="true"> MB</string>
212
+                  </property>
213
+                  <property name="minimum">
214
+                   <number>20</number>
215
+                  </property>
216
+                  <property name="maximum">
217
+                   <number>8192</number>
218
+                  </property>
219
+                  <property name="value">
220
+                   <number>512</number>
221
+                  </property>
222
+                 </widget>
223
+                </item>
224
+                <item row="2" column="1">
225
+                 <widget class="QLabel" name="label_45">
226
+                  <property name="text">
227
+                   <string>Basic.Settings.Output.ReplayBuffer.HotkeyMessage</string>
228
+                  </property>
229
+                 </widget>
230
+                </item>
231
+                <item row="3" column="1">
232
+                 <widget class="QLabel" name="simpleRBEstimate">
233
+                  <property name="text">
234
+                   <string notr="true"/>
235
+                  </property>
236
+                 </widget>
237
                 </item>
238
                </layout>
239
               </widget>
240
@@ -1064,6 +1149,20 @@
241
                             </property>
242
                            </widget>
243
                           </item>
244
+                          <item>
245
+                           <widget class="QRadioButton" name="advOutTrack5">
246
+                            <property name="text">
247
+                             <string notr="true">5</string>
248
+                            </property>
249
+                           </widget>
250
+                          </item>
251
+                          <item>
252
+                           <widget class="QRadioButton" name="advOutTrack6">
253
+                            <property name="text">
254
+                             <string notr="true">6</string>
255
+                            </property>
256
+                           </widget>
257
+                          </item>
258
                          </layout>
259
                         </widget>
260
                        </item>
261
@@ -1407,6 +1506,20 @@
262
                                 </property>
263
                                </widget>
264
                               </item>
265
+                              <item>
266
+                               <widget class="QCheckBox" name="advOutRecTrack5">
267
+                                <property name="text">
268
+                                 <string notr="true">5</string>
269
+                                </property>
270
+                               </widget>
271
+                              </item>
272
+                              <item>
273
+                               <widget class="QCheckBox" name="advOutRecTrack6">
274
+                                <property name="text">
275
+                                 <string notr="true">6</string>
276
+                                </property>
277
+                               </widget>
278
+                              </item>
279
                              </layout>
280
                             </widget>
281
                            </item>
282
@@ -1774,6 +1887,20 @@
283
                           </property>
284
                          </widget>
285
                         </item>
286
+                        <item>
287
+                         <widget class="QRadioButton" name="advOutFFTrack5">
288
+                          <property name="text">
289
+                           <string notr="true">5</string>
290
+                          </property>
291
+                         </widget>
292
+                        </item>
293
+                        <item>
294
+                         <widget class="QRadioButton" name="advOutFFTrack6">
295
+                          <property name="text">
296
+                           <string notr="true">6</string>
297
+                          </property>
298
+                         </widget>
299
+                        </item>
300
                        </layout>
301
                       </widget>
302
                      </item>
303
@@ -2357,6 +2484,236 @@
304
                       </layout>
305
                      </widget>
306
                     </item>
307
+                    <item>
308
+                     <widget class="QGroupBox" name="groupBox_9">
309
+                      <property name="sizePolicy">
310
+                       <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
311
+                        <horstretch>0</horstretch>
312
+                        <verstretch>0</verstretch>
313
+                       </sizepolicy>
314
+                      </property>
315
+                      <property name="title">
316
+                       <string>Basic.Settings.Output.Adv.Audio.Track5</string>
317
+                      </property>
318
+                      <layout class="QFormLayout" name="formLayout_25">
319
+                       <property name="fieldGrowthPolicy">
320
+                        <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
321
+                       </property>
322
+                       <property name="labelAlignment">
323
+                        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
324
+                       </property>
325
+                       <item row="0" column="0">
326
+                        <widget class="QLabel" name="label_59">
327
+                         <property name="minimumSize">
328
+                          <size>
329
+                           <width>170</width>
330
+                           <height>0</height>
331
+                          </size>
332
+                         </property>
333
+                         <property name="text">
334
+                          <string>Basic.Settings.Output.AudioBitrate</string>
335
+                         </property>
336
+                         <property name="alignment">
337
+                          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
338
+                         </property>
339
+                         <property name="buddy">
340
+                          <cstring>advOutTrack5Bitrate</cstring>
341
+                         </property>
342
+                        </widget>
343
+                       </item>
344
+                       <item row="0" column="1">
345
+                        <widget class="QComboBox" name="advOutTrack5Bitrate">
346
+                         <property name="currentIndex">
347
+                          <number>8</number>
348
+                         </property>
349
+                         <item>
350
+                          <property name="text">
351
+                           <string>32</string>
352
+                          </property>
353
+                         </item>
354
+                         <item>
355
+                          <property name="text">
356
+                           <string>48</string>
357
+                          </property>
358
+                         </item>
359
+                         <item>
360
+                          <property name="text">
361
+                           <string>64</string>
362
+                          </property>
363
+                         </item>
364
+                         <item>
365
+                          <property name="text">
366
+                           <string>80</string>
367
+                          </property>
368
+                         </item>
369
+                         <item>
370
+                          <property name="text">
371
+                           <string>96</string>
372
+                          </property>
373
+                         </item>
374
+                         <item>
375
+                          <property name="text">
376
+                           <string>112</string>
377
+                          </property>
378
+                         </item>
379
+                         <item>
380
+                          <property name="text">
381
+                           <string>128</string>
382
+                          </property>
383
+                         </item>
384
+                         <item>
385
+                          <property name="text">
386
+                           <string>160</string>
387
+                          </property>
388
+                         </item>
389
+                         <item>
390
+                          <property name="text">
391
+                           <string>192</string>
392
+                          </property>
393
+                         </item>
394
+                         <item>
395
+                          <property name="text">
396
+                           <string>256</string>
397
+                          </property>
398
+                         </item>
399
+                         <item>
400
+                          <property name="text">
401
+                           <string>320</string>
402
+                          </property>
403
+                         </item>
404
+                        </widget>
405
+                       </item>
406
+                       <item row="1" column="0">
407
+                        <widget class="QLabel" name="label_60">
408
+                         <property name="text">
409
+                          <string>Name</string>
410
+                         </property>
411
+                         <property name="buddy">
412
+                          <cstring>advOutTrack5Name</cstring>
413
+                         </property>
414
+                        </widget>
415
+                       </item>
416
+                       <item row="1" column="1">
417
+                        <widget class="QLineEdit" name="advOutTrack5Name"/>
418
+                       </item>
419
+                      </layout>
420
+                     </widget>
421
+                    </item>
422
+                    <item>
423
+                     <widget class="QGroupBox" name="groupBox_12">
424
+                      <property name="sizePolicy">
425
+                       <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
426
+                        <horstretch>0</horstretch>
427
+                        <verstretch>0</verstretch>
428
+                       </sizepolicy>
429
+                      </property>
430
+                      <property name="title">
431
+                       <string>Basic.Settings.Output.Adv.Audio.Track6</string>
432
+                      </property>
433
+                      <layout class="QFormLayout" name="formLayout_26">
434
+                       <property name="fieldGrowthPolicy">
435
+                        <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
436
+                       </property>
437
+                       <property name="labelAlignment">
438
+                        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
439
+                       </property>
440
+                       <item row="0" column="0">
441
+                        <widget class="QLabel" name="label_61">
442
+                         <property name="minimumSize">
443
+                          <size>
444
+                           <width>170</width>
445
+                           <height>0</height>
446
+                          </size>
447
+                         </property>
448
+                         <property name="text">
449
+                          <string>Basic.Settings.Output.AudioBitrate</string>
450
+                         </property>
451
+                         <property name="alignment">
452
+                          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
453
+                         </property>
454
+                         <property name="buddy">
455
+                          <cstring>advOutTrack6Bitrate</cstring>
456
+                         </property>
457
+                        </widget>
458
+                       </item>
459
+                       <item row="0" column="1">
460
+                        <widget class="QComboBox" name="advOutTrack6Bitrate">
461
+                         <property name="currentIndex">
462
+                          <number>8</number>
463
+                         </property>
464
+                         <item>
465
+                          <property name="text">
466
+                           <string>32</string>
467
+                          </property>
468
+                         </item>
469
+                         <item>
470
+                          <property name="text">
471
+                           <string>48</string>
472
+                          </property>
473
+                         </item>
474
+                         <item>
475
+                          <property name="text">
476
+                           <string>64</string>
477
+                          </property>
478
+                         </item>
479
+                         <item>
480
+                          <property name="text">
481
+                           <string>80</string>
482
+                          </property>
483
+                         </item>
484
+                         <item>
485
+                          <property name="text">
486
+                           <string>96</string>
487
+                          </property>
488
+                         </item>
489
+                         <item>
490
+                          <property name="text">
491
+                           <string>112</string>
492
+                          </property>
493
+                         </item>
494
+                         <item>
495
+                          <property name="text">
496
+                           <string>128</string>
497
+                          </property>
498
+                         </item>
499
+                         <item>
500
+                          <property name="text">
501
+                           <string>160</string>
502
+                          </property>
503
+                         </item>
504
+                         <item>
505
+                          <property name="text">
506
+                           <string>192</string>
507
+                          </property>
508
+                         </item>
509
+                         <item>
510
+                          <property name="text">
511
+                           <string>256</string>
512
+                          </property>
513
+                         </item>
514
+                         <item>
515
+                          <property name="text">
516
+                           <string>320</string>
517
+                          </property>
518
+                         </item>
519
+                        </widget>
520
+                       </item>
521
+                       <item row="1" column="0">
522
+                        <widget class="QLabel" name="label_62">
523
+                         <property name="text">
524
+                          <string>Name</string>
525
+                         </property>
526
+                         <property name="buddy">
527
+                          <cstring>advOutTrack6Name</cstring>
528
+                         </property>
529
+                        </widget>
530
+                       </item>
531
+                       <item row="1" column="1">
532
+                        <widget class="QLineEdit" name="advOutTrack6Name"/>
533
+                       </item>
534
+                      </layout>
535
+                     </widget>
536
+                    </item>
537
                    </layout>
538
                   </widget>
539
                  </item>
540
@@ -2545,8 +2902,8 @@
541
              <rect>
542
               <x>0</x>
543
               <y>0</y>
544
-              <width>80</width>
545
-              <height>16</height>
546
+              <width>800</width>
547
+              <height>69</height>
548
              </rect>
549
             </property>
550
            </widget>
551
@@ -2911,8 +3268,8 @@
552
              <rect>
553
               <x>0</x>
554
               <y>0</y>
555
-              <width>559</width>
556
-              <height>681</height>
557
+              <width>593</width>
558
+              <height>709</height>
559
              </rect>
560
             </property>
561
             <layout class="QVBoxLayout" name="verticalLayout_16">
562
@@ -3108,6 +3465,9 @@
563
                    <string>Basic.Settings.Output.Adv.Recording</string>
564
                   </property>
565
                   <layout class="QFormLayout" name="formLayout_17">
566
+                   <property name="labelAlignment">
567
+                    <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
568
+                   </property>
569
                    <item row="0" column="0">
570
                     <widget class="QLabel" name="label_7">
571
                      <property name="text">
572
@@ -3125,6 +3485,42 @@
573
                      </property>
574
                     </widget>
575
                    </item>
576
+                   <item row="2" column="1">
577
+                    <layout class="QHBoxLayout" name="horizontalLayout_14">
578
+                     <property name="leftMargin">
579
+                      <number>0</number>
580
+                     </property>
581
+                     <property name="topMargin">
582
+                      <number>0</number>
583
+                     </property>
584
+                     <property name="rightMargin">
585
+                      <number>0</number>
586
+                     </property>
587
+                     <property name="bottomMargin">
588
+                      <number>0</number>
589
+                     </property>
590
+                     <item>
591
+                      <widget class="QLineEdit" name="simpleRBPrefix"/>
592
+                     </item>
593
+                     <item>
594
+                      <widget class="QLabel" name="label_58">
595
+                       <property name="text">
596
+                        <string>Basic.Settings.Output.ReplayBuffer.Suffix</string>
597
+                       </property>
598
+                      </widget>
599
+                     </item>
600
+                     <item>
601
+                      <widget class="QLineEdit" name="simpleRBSuffix"/>
602
+                     </item>
603
+                    </layout>
604
+                   </item>
605
+                   <item row="2" column="0">
606
+                    <widget class="QLabel" name="label_57">
607
+                     <property name="text">
608
+                      <string>Basic.Settings.Output.ReplayBuffer.Prefix</string>
609
+                     </property>
610
+                    </widget>
611
+                   </item>
612
                   </layout>
613
                  </widget>
614
                 </item>
615
@@ -3384,12 +3780,12 @@
616
    <slot>setCurrentIndex(int)</slot>
617
    <hints>
618
     <hint type="sourcelabel">
619
-     <x>310</x>
620
-     <y>29</y>
621
+     <x>159</x>
622
+     <y>30</y>
623
     </hint>
624
     <hint type="destinationlabel">
625
      <x>241</x>
626
-     <y>34</y>
627
+     <y>30</y>
628
     </hint>
629
    </hints>
630
   </connection>
631
@@ -3400,12 +3796,12 @@
632
    <slot>setCurrentIndex(int)</slot>
633
    <hints>
634
     <hint type="sourcelabel">
635
-     <x>250</x>
636
-     <y>39</y>
637
+     <x>586</x>
638
+     <y>38</y>
639
     </hint>
640
     <hint type="destinationlabel">
641
-     <x>250</x>
642
-     <y>39</y>
643
+     <x>401</x>
644
+     <y>102</y>
645
     </hint>
646
    </hints>
647
   </connection>
648
@@ -3416,12 +3812,12 @@
649
    <slot>setVisible(bool)</slot>
650
    <hints>
651
     <hint type="sourcelabel">
652
-     <x>250</x>
653
-     <y>39</y>
654
+     <x>640</x>
655
+     <y>180</y>
656
     </hint>
657
     <hint type="destinationlabel">
658
-     <x>250</x>
659
-     <y>39</y>
660
+     <x>640</x>
661
+     <y>229</y>
662
     </hint>
663
    </hints>
664
   </connection>
665
@@ -3432,12 +3828,12 @@
666
    <slot>setVisible(bool)</slot>
667
    <hints>
668
     <hint type="sourcelabel">
669
-     <x>250</x>
670
-     <y>39</y>
671
+     <x>640</x>
672
+     <y>180</y>
673
     </hint>
674
     <hint type="destinationlabel">
675
-     <x>250</x>
676
-     <y>39</y>
677
+     <x>383</x>
678
+     <y>229</y>
679
     </hint>
680
    </hints>
681
   </connection>
682
@@ -3448,12 +3844,12 @@
683
    <slot>setVisible(bool)</slot>
684
    <hints>
685
     <hint type="sourcelabel">
686
-     <x>250</x>
687
-     <y>39</y>
688
+     <x>640</x>
689
+     <y>180</y>
690
     </hint>
691
     <hint type="destinationlabel">
692
-     <x>250</x>
693
-     <y>39</y>
694
+     <x>640</x>
695
+     <y>255</y>
696
     </hint>
697
    </hints>
698
   </connection>
699
@@ -3464,12 +3860,12 @@
700
    <slot>setVisible(bool)</slot>
701
    <hints>
702
     <hint type="sourcelabel">
703
-     <x>250</x>
704
-     <y>39</y>
705
+     <x>640</x>
706
+     <y>180</y>
707
     </hint>
708
     <hint type="destinationlabel">
709
-     <x>250</x>
710
-     <y>39</y>
711
+     <x>383</x>
712
+     <y>255</y>
713
     </hint>
714
    </hints>
715
   </connection>
716
@@ -3480,12 +3876,12 @@
717
    <slot>setCurrentIndex(int)</slot>
718
    <hints>
719
     <hint type="sourcelabel">
720
-     <x>259</x>
721
-     <y>48</y>
722
+     <x>606</x>
723
+     <y>113</y>
724
     </hint>
725
     <hint type="destinationlabel">
726
-     <x>241</x>
727
-     <y>30</y>
728
+     <x>394</x>
729
+     <y>191</y>
730
     </hint>
731
    </hints>
732
   </connection>
733
@@ -3496,12 +3892,12 @@
734
    <slot>setEnabled(bool)</slot>
735
    <hints>
736
     <hint type="sourcelabel">
737
-     <x>259</x>
738
-     <y>60</y>
739
+     <x>397</x>
740
+     <y>323</y>
741
     </hint>
742
     <hint type="destinationlabel">
743
-     <x>228</x>
744
-     <y>50</y>
745
+     <x>676</x>
746
+     <y>323</y>
747
     </hint>
748
    </hints>
749
   </connection>
750
@@ -3512,12 +3908,12 @@
751
    <slot>setEnabled(bool)</slot>
752
    <hints>
753
     <hint type="sourcelabel">
754
-     <x>259</x>
755
-     <y>39</y>
756
+     <x>330</x>
757
+     <y>191</y>
758
     </hint>
759
     <hint type="destinationlabel">
760
-     <x>228</x>
761
-     <y>29</y>
762
+     <x>591</x>
763
+     <y>191</y>
764
     </hint>
765
    </hints>
766
   </connection>
767
@@ -3528,12 +3924,12 @@
768
    <slot>setEnabled(bool)</slot>
769
    <hints>
770
     <hint type="sourcelabel">
771
-     <x>259</x>
772
-     <y>60</y>
773
+     <x>353</x>
774
+     <y>277</y>
775
     </hint>
776
     <hint type="destinationlabel">
777
-     <x>228</x>
778
-     <y>50</y>
779
+     <x>614</x>
780
+     <y>277</y>
781
     </hint>
782
    </hints>
783
   </connection>
784
@@ -3544,12 +3940,12 @@
785
    <slot>setCurrentIndex(int)</slot>
786
    <hints>
787
     <hint type="sourcelabel">
788
-     <x>259</x>
789
-     <y>60</y>
790
+     <x>676</x>
791
+     <y>148</y>
792
     </hint>
793
     <hint type="destinationlabel">
794
-     <x>259</x>
795
-     <y>60</y>
796
+     <x>676</x>
797
+     <y>177</y>
798
     </hint>
799
    </hints>
800
   </connection>
801
@@ -3560,12 +3956,12 @@
802
    <slot>setEnabled(bool)</slot>
803
    <hints>
804
     <hint type="sourcelabel">
805
-     <x>250</x>
806
-     <y>39</y>
807
+     <x>724</x>
808
+     <y>436</y>
809
     </hint>
810
     <hint type="destinationlabel">
811
-     <x>250</x>
812
-     <y>39</y>
813
+     <x>397</x>
814
+     <y>462</y>
815
     </hint>
816
    </hints>
817
   </connection>
818
@@ -3576,12 +3972,12 @@
819
    <slot>setEnabled(bool)</slot>
820
    <hints>
821
     <hint type="sourcelabel">
822
-     <x>250</x>
823
-     <y>39</y>
824
+     <x>724</x>
825
+     <y>436</y>
826
     </hint>
827
     <hint type="destinationlabel">
828
-     <x>250</x>
829
-     <y>39</y>
830
+     <x>724</x>
831
+     <y>485</y>
832
     </hint>
833
    </hints>
834
   </connection>
835
@@ -3592,12 +3988,12 @@
836
    <slot>setEnabled(bool)</slot>
837
    <hints>
838
     <hint type="sourcelabel">
839
-     <x>250</x>
840
-     <y>39</y>
841
+     <x>724</x>
842
+     <y>436</y>
843
     </hint>
844
     <hint type="destinationlabel">
845
-     <x>250</x>
846
-     <y>39</y>
847
+     <x>724</x>
848
+     <y>462</y>
849
     </hint>
850
    </hints>
851
   </connection>
852
@@ -3608,12 +4004,12 @@
853
    <slot>setEnabled(bool)</slot>
854
    <hints>
855
     <hint type="sourcelabel">
856
-     <x>250</x>
857
-     <y>39</y>
858
+     <x>724</x>
859
+     <y>541</y>
860
     </hint>
861
     <hint type="destinationlabel">
862
-     <x>250</x>
863
-     <y>39</y>
864
+     <x>332</x>
865
+     <y>567</y>
866
     </hint>
867
    </hints>
868
   </connection>
869
@@ -3624,12 +4020,12 @@
870
    <slot>setEnabled(bool)</slot>
871
    <hints>
872
     <hint type="sourcelabel">
873
-     <x>250</x>
874
-     <y>39</y>
875
+     <x>724</x>
876
+     <y>541</y>
877
     </hint>
878
     <hint type="destinationlabel">
879
-     <x>250</x>
880
-     <y>39</y>
881
+     <x>724</x>
882
+     <y>567</y>
883
     </hint>
884
    </hints>
885
   </connection>
886
@@ -3640,12 +4036,12 @@
887
    <slot>setEnabled(bool)</slot>
888
    <hints>
889
     <hint type="sourcelabel">
890
-     <x>250</x>
891
-     <y>39</y>
892
+     <x>724</x>
893
+     <y>541</y>
894
     </hint>
895
     <hint type="destinationlabel">
896
-     <x>250</x>
897
-     <y>39</y>
898
+     <x>332</x>
899
+     <y>593</y>
900
     </hint>
901
    </hints>
902
   </connection>
903
@@ -3656,12 +4052,12 @@
904
    <slot>setEnabled(bool)</slot>
905
    <hints>
906
     <hint type="sourcelabel">
907
-     <x>250</x>
908
-     <y>39</y>
909
+     <x>724</x>
910
+     <y>541</y>
911
     </hint>
912
     <hint type="destinationlabel">
913
-     <x>250</x>
914
-     <y>39</y>
915
+     <x>724</x>
916
+     <y>593</y>
917
     </hint>
918
    </hints>
919
   </connection>
920
@@ -3672,12 +4068,12 @@
921
    <slot>setEnabled(bool)</slot>
922
    <hints>
923
     <hint type="sourcelabel">
924
-     <x>720</x>
925
-     <y>280</y>
926
+     <x>951</x>
927
+     <y>349</y>
928
     </hint>
929
     <hint type="destinationlabel">
930
      <x>346</x>
931
-     <y>306</y>
932
+     <y>375</y>
933
     </hint>
934
    </hints>
935
   </connection>
936
@@ -3688,12 +4084,12 @@
937
    <slot>setEnabled(bool)</slot>
938
    <hints>
939
     <hint type="sourcelabel">
940
-     <x>761</x>
941
-     <y>280</y>
942
+     <x>951</x>
943
+     <y>349</y>
944
     </hint>
945
     <hint type="destinationlabel">
946
-     <x>778</x>
947
-     <y>306</y>
948
+     <x>951</x>
949
+     <y>375</y>
950
     </hint>
951
    </hints>
952
   </connection>
953
@@ -3704,12 +4100,12 @@
954
    <slot>setEnabled(bool)</slot>
955
    <hints>
956
     <hint type="sourcelabel">
957
-     <x>820</x>
958
-     <y>280</y>
959
+     <x>951</x>
960
+     <y>349</y>
961
     </hint>
962
     <hint type="destinationlabel">
963
-     <x>810</x>
964
-     <y>329</y>
965
+     <x>951</x>
966
+     <y>398</y>
967
     </hint>
968
    </hints>
969
   </connection>
970
@@ -3720,12 +4116,12 @@
971
    <slot>setEnabled(bool)</slot>
972
    <hints>
973
     <hint type="sourcelabel">
974
-     <x>862</x>
975
-     <y>280</y>
976
+     <x>951</x>
977
+     <y>349</y>
978
     </hint>
979
     <hint type="destinationlabel">
980
-     <x>859</x>
981
-     <y>352</y>
982
+     <x>951</x>
983
+     <y>421</y>
984
     </hint>
985
    </hints>
986
   </connection>
987
@@ -3736,12 +4132,12 @@
988
    <slot>setEnabled(bool)</slot>
989
    <hints>
990
     <hint type="sourcelabel">
991
-     <x>866</x>
992
-     <y>280</y>
993
+     <x>951</x>
994
+     <y>349</y>
995
     </hint>
996
     <hint type="destinationlabel">
997
-     <x>866</x>
998
-     <y>375</y>
999
+     <x>951</x>
1000
+     <y>444</y>
1001
     </hint>
1002
    </hints>
1003
   </connection>
1004
@@ -3752,12 +4148,12 @@
1005
    <slot>setVisible(bool)</slot>
1006
    <hints>
1007
     <hint type="sourcelabel">
1008
-     <x>250</x>
1009
-     <y>39</y>
1010
+     <x>640</x>
1011
+     <y>180</y>
1012
     </hint>
1013
     <hint type="destinationlabel">
1014
-     <x>250</x>
1015
-     <y>39</y>
1016
+     <x>640</x>
1017
+     <y>203</y>
1018
     </hint>
1019
    </hints>
1020
   </connection>
1021
@@ -3768,12 +4164,12 @@
1022
    <slot>setEnabled(bool)</slot>
1023
    <hints>
1024
     <hint type="sourcelabel">
1025
-     <x>404</x>
1026
-     <y>193</y>
1027
+     <x>705</x>
1028
+     <y>225</y>
1029
     </hint>
1030
     <hint type="destinationlabel">
1031
-     <x>404</x>
1032
-     <y>219</y>
1033
+     <x>705</x>
1034
+     <y>248</y>
1035
     </hint>
1036
    </hints>
1037
   </connection>
1038
@@ -3784,12 +4180,12 @@
1039
    <slot>setEnabled(bool)</slot>
1040
    <hints>
1041
     <hint type="sourcelabel">
1042
-     <x>404</x>
1043
-     <y>245</y>
1044
+     <x>705</x>
1045
+     <y>271</y>
1046
     </hint>
1047
     <hint type="destinationlabel">
1048
-     <x>404</x>
1049
-     <y>271</y>
1050
+     <x>705</x>
1051
+     <y>294</y>
1052
     </hint>
1053
    </hints>
1054
   </connection>
1055
obs-studio-0.16.6.tar.xz/UI/forms/OBSBasicTransform.ui -> obs-studio-0.17.0.tar.xz/UI/forms/OBSBasicTransform.ui Changed
15
 
1
@@ -648,5 +648,12 @@
2
   </layout>
3
  </widget>
4
  <resources/>
5
- <connections/>
6
+ <connections>
7
+  <connection>
8
+   <sender>buttonBox</sender>
9
+   <signal>rejected()</signal>
10
+   <receiver>OBSBasicTransform</receiver>
11
+   <slot>reject()</slot>
12
+  </connection>
13
+ </connections>
14
 </ui>
15
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/CMakeLists.txt -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/CMakeLists.txt Changed
55
 
1
@@ -17,9 +17,15 @@
2
        )
3
 endif()
4
 
5
+configure_file(
6
+   "${CMAKE_CURRENT_SOURCE_DIR}/frontend-tools-config.h.in"
7
+   "${CMAKE_BINARY_DIR}/config/frontend-tools-config.h")
8
+
9
 set(frontend-tools_HEADERS
10
    ${frontend-tools_HEADERS}
11
+   "${CMAKE_BINARY_DIR}/config/frontend-tools-config.h"
12
    output-timer.hpp
13
+   tool-helpers.hpp
14
    )
15
 set(frontend-tools_SOURCES
16
    ${frontend-tools_SOURCES}
17
@@ -34,6 +40,18 @@
18
 if(WIN32)
19
    set(frontend-tools_PLATFORM_SOURCES
20
        auto-scene-switcher-win.cpp)
21
+
22
+   if(BUILD_CAPTIONS)
23
+       set(frontend-tools_PLATFORM_SOURCES
24
+           ${frontend-tools_PLATFORM_SOURCES}
25
+           captions.cpp
26
+           captions-stream.cpp)
27
+       set(frontend-tools_PLATFORM_HEADERS
28
+           captions.hpp
29
+           captions-stream.hpp)
30
+       set(frontend-tools_PLATFORM_UI
31
+           forms/captions.ui)
32
+   endif()
33
 elseif(APPLE)
34
    set(frontend-tools_PLATFORM_SOURCES
35
        auto-scene-switcher-osx.mm)
36
@@ -44,13 +62,16 @@
37
        ${COCOA})
38
 endif()
39
 
40
-qt5_wrap_ui(frontend-tools_UI_HEADERS ${frontend-tools_UI})
41
+qt5_wrap_ui(frontend-tools_UI_HEADERS
42
+   ${frontend-tools_UI}
43
+   ${frontend-tools_PLATFORM_UI})
44
 
45
 add_library(frontend-tools MODULE
46
    ${frontend-tools_HEADERS}
47
    ${frontend-tools_SOURCES}
48
-   ${frontend-tools_PLATFORM_SOURCES}
49
    ${frontend-tools_UI_HEADERS}
50
+   ${frontend-tools_PLATFORM_SOURCES}
51
+   ${frontend-tools_PLATFORM_HEADERS}
52
    )
53
 target_link_libraries(frontend-tools
54
    ${frontend-tools_PLATFORM_LIBS}
55
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/auto-scene-switcher.cpp -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/auto-scene-switcher.cpp Changed
47
 
1
@@ -6,6 +6,7 @@
2
 #include <QMessageBox>
3
 #include <QAction>
4
 #include "auto-scene-switcher.hpp"
5
+#include "tool-helpers.hpp"
6
 
7
 #include <condition_variable>
8
 #include <chrono>
9
@@ -82,37 +83,6 @@
10
    return QStringLiteral("[") + scene + QStringLiteral("]: ") + window;
11
 }
12
 
13
-static inline string GetWeakSourceName(obs_weak_source_t *weak_source)
14
-{
15
-   string name;
16
-
17
-   obs_source_t *source = obs_weak_source_get_source(weak_source);
18
-   if (source) {
19
-       name = obs_source_get_name(source);
20
-       obs_source_release(source);
21
-   }
22
-
23
-   return name;
24
-}
25
-
26
-static inline OBSWeakSource GetWeakSourceByName(const char *name)
27
-{
28
-   OBSWeakSource weak;
29
-   obs_source_t *source = obs_get_source_by_name(name);
30
-   if (source) {
31
-       weak = obs_source_get_weak_source(source);
32
-       obs_weak_source_release(weak);
33
-       obs_source_release(source);
34
-   }
35
-
36
-   return weak;
37
-}
38
-
39
-static inline OBSWeakSource GetWeakSourceByQString(const QString &name)
40
-{
41
-   return GetWeakSourceByName(name.toUtf8().constData());
42
-}
43
-
44
 SceneSwitcher::SceneSwitcher(QWidget *parent)
45
    : QDialog(parent),
46
      ui(new Ui_SceneSwitcher)
47
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/captions-stream.cpp Added
420
 
1
@@ -0,0 +1,418 @@
2
+#include "captions-stream.hpp"
3
+#include <mmreg.h>
4
+#include <util/windows/CoTaskMemPtr.hpp>
5
+#include <util/threading.h>
6
+#include <util/base.h>
7
+
8
+using namespace std;
9
+
10
+#if 0
11
+#define debugfunc(format, ...) blog(LOG_DEBUG, "[Captions] %s(" format ")", \
12
+       __FUNCTION__, ##__VA_ARGS__)
13
+#else
14
+#define debugfunc(format, ...)
15
+#endif
16
+
17
+CaptionStream::CaptionStream(DWORD samplerate_) :
18
+   samplerate(samplerate_),
19
+   event(CreateEvent(nullptr, false, false, nullptr))
20
+{
21
+   buf_info.ulMsMinNotification = 50;
22
+   buf_info.ulMsBufferSize = 500;
23
+   buf_info.ulMsEventBias = 0;
24
+
25
+   format.wFormatTag = WAVE_FORMAT_PCM;
26
+   format.nChannels = 1;
27
+   format.nSamplesPerSec = 16000;
28
+   format.nAvgBytesPerSec = format.nSamplesPerSec * sizeof(uint16_t);
29
+   format.nBlockAlign = 2;
30
+   format.wBitsPerSample = 16;
31
+   format.cbSize = sizeof(format);
32
+
33
+   resampler.Reset(&format);
34
+}
35
+
36
+void CaptionStream::Stop()
37
+{
38
+   {
39
+       lock_guard<mutex> lock(m);
40
+       circlebuf_free(buf);
41
+   }
42
+
43
+   cv.notify_one();
44
+}
45
+
46
+void CaptionStream::PushAudio(const struct audio_data *data, bool muted)
47
+{
48
+   uint8_t *output[MAX_AV_PLANES] = {};
49
+   uint32_t frames = data->frames;
50
+   uint64_t ts_offset;
51
+   bool ready = false;
52
+
53
+   audio_resampler_resample(resampler, output, &frames, &ts_offset,
54
+           data->data, data->frames);
55
+
56
+   if (output[0]) {
57
+       if (muted)
58
+           memset(output[0], 0, frames * sizeof(int16_t));
59
+
60
+       lock_guard<mutex> lock(m);
61
+       circlebuf_push_back(buf, output[0], frames * sizeof(int16_t));
62
+       write_pos += frames * sizeof(int16_t);
63
+
64
+       if (wait_size && buf->size >= wait_size)
65
+           ready = true;
66
+   }
67
+
68
+   if (ready)
69
+       cv.notify_one();
70
+}
71
+
72
+// IUnknown methods
73
+
74
+STDMETHODIMP CaptionStream::QueryInterface(REFIID riid, void **ppv)
75
+{
76
+   if (riid == IID_IUnknown) {
77
+       AddRef();
78
+       *ppv = this;
79
+
80
+   } else if (riid == IID_IStream) {
81
+       AddRef();
82
+       *ppv = (IStream*)this;
83
+
84
+   } else if (riid == IID_ISpStreamFormat) {
85
+       AddRef();
86
+       *ppv = (ISpStreamFormat*)this;
87
+
88
+   } else if (riid == IID_ISpAudio) {
89
+       AddRef();
90
+       *ppv = (ISpAudio*)this;
91
+
92
+   } else {
93
+       *ppv = nullptr;
94
+       return E_NOINTERFACE;
95
+   }
96
+
97
+   return NOERROR;
98
+}
99
+
100
+STDMETHODIMP_(ULONG) CaptionStream::AddRef()
101
+{
102
+   return (ULONG)os_atomic_inc_long(&refs);
103
+}
104
+
105
+STDMETHODIMP_(ULONG) CaptionStream::Release()
106
+{
107
+   ULONG new_refs = (ULONG)os_atomic_dec_long(&refs);
108
+   if (!new_refs)
109
+       delete this;
110
+
111
+   return new_refs;
112
+}
113
+
114
+// ISequentialStream methods
115
+
116
+STDMETHODIMP CaptionStream::Read(void *data, ULONG bytes, ULONG *read_bytes)
117
+{
118
+   HRESULT hr = S_OK;
119
+   size_t cur_size;
120
+
121
+   debugfunc("data, %lu, read_bytes", bytes);
122
+   if (!data)
123
+       return STG_E_INVALIDPOINTER;
124
+
125
+   {
126
+       lock_guard<mutex> lock1(m);
127
+       wait_size = bytes;
128
+       cur_size = buf->size;
129
+   }
130
+
131
+   unique_lock<mutex> lock(m);
132
+
133
+   if (bytes > cur_size)
134
+       cv.wait(lock);
135
+
136
+   if (bytes > (ULONG)buf->size) {
137
+       bytes = (ULONG)buf->size;
138
+       hr = S_FALSE;
139
+   }
140
+   if (bytes)
141
+       circlebuf_pop_front(buf, data, bytes);
142
+   if (read_bytes)
143
+       *read_bytes = bytes;
144
+
145
+   wait_size = 0;
146
+   pos.QuadPart += bytes;
147
+   return hr;
148
+}
149
+
150
+STDMETHODIMP CaptionStream::Write(const void *, ULONG bytes,
151
+       ULONG*)
152
+{
153
+   debugfunc("data, %lu, written_bytes", bytes);
154
+   UNUSED_PARAMETER(bytes);
155
+
156
+   return STG_E_INVALIDFUNCTION;
157
+}
158
+
159
+// IStream methods
160
+
161
+STDMETHODIMP CaptionStream::Seek(LARGE_INTEGER move, DWORD origin,
162
+       ULARGE_INTEGER *new_pos)
163
+{
164
+   debugfunc("%lld, %lx, new_pos", move, origin);
165
+   UNUSED_PARAMETER(move);
166
+   UNUSED_PARAMETER(origin);
167
+
168
+   if (!new_pos)
169
+       return E_POINTER;
170
+
171
+   if (origin != SEEK_CUR || move.QuadPart != 0)
172
+       return E_NOTIMPL;
173
+
174
+   *new_pos = pos;
175
+   return S_OK;
176
+}
177
+
178
+STDMETHODIMP CaptionStream::SetSize(ULARGE_INTEGER new_size)
179
+{
180
+   debugfunc("%llu", new_size);
181
+   UNUSED_PARAMETER(new_size);
182
+   return STG_E_INVALIDFUNCTION;
183
+}
184
+
185
+STDMETHODIMP CaptionStream::CopyTo(IStream *stream, ULARGE_INTEGER bytes,
186
+       ULARGE_INTEGER *read_bytes,
187
+       ULARGE_INTEGER *written_bytes)
188
+{
189
+   HRESULT hr;
190
+
191
+   debugfunc("stream, %llu, read_bytes, written_bytes", bytes);
192
+
193
+   if (!stream)
194
+       return STG_E_INVALIDPOINTER;
195
+
196
+   ULONG written = 0;
197
+   if (bytes.QuadPart > (ULONGLONG)buf->size)
198
+       bytes.QuadPart = (ULONGLONG)buf->size;
199
+
200
+   lock_guard<mutex> lock(m);
201
+   temp_buf.resize((size_t)bytes.QuadPart);
202
+   circlebuf_peek_front(buf, &temp_buf[0], (size_t)bytes.QuadPart);
203
+
204
+   hr = stream->Write(temp_buf.data(), (ULONG)bytes.QuadPart, &written);
205
+
206
+   if (read_bytes)
207
+       *read_bytes = bytes;
208
+   if (written_bytes)
209
+       written_bytes->QuadPart = written;
210
+
211
+   return hr;
212
+}
213
+
214
+STDMETHODIMP CaptionStream::Commit(DWORD commit_flags)
215
+{
216
+   debugfunc("%lx", commit_flags);
217
+   UNUSED_PARAMETER(commit_flags);
218
+   /* TODO? */
219
+   return S_OK;
220
+}
221
+
222
+STDMETHODIMP CaptionStream::Revert(void)
223
+{
224
+   debugfunc("");
225
+   return S_OK;
226
+}
227
+
228
+STDMETHODIMP CaptionStream::LockRegion(ULARGE_INTEGER offset,
229
+       ULARGE_INTEGER size, DWORD type)
230
+{
231
+   debugfunc("%llu, %llu, %ld", offset, size, type);
232
+   UNUSED_PARAMETER(offset);
233
+   UNUSED_PARAMETER(size);
234
+   UNUSED_PARAMETER(type);
235
+   /* TODO? */
236
+   return STG_E_INVALIDFUNCTION;
237
+}
238
+
239
+STDMETHODIMP CaptionStream::UnlockRegion(ULARGE_INTEGER offset,
240
+       ULARGE_INTEGER size, DWORD type)
241
+{
242
+   debugfunc("%llu, %llu, %ld", offset, size, type);
243
+   UNUSED_PARAMETER(offset);
244
+   UNUSED_PARAMETER(size);
245
+   UNUSED_PARAMETER(type);
246
+   /* TODO? */
247
+   return STG_E_INVALIDFUNCTION;
248
+}
249
+
250
+static const wchar_t *stat_name = L"Caption stream";
251
+
252
+STDMETHODIMP CaptionStream::Stat(STATSTG *stg, DWORD flag)
253
+{
254
+   debugfunc("stg, %lu", flag);
255
+
256
+   if (!stg)
257
+       return E_POINTER;
258
+
259
+   lock_guard<mutex> lock(m);
260
+   *stg = {};
261
+   stg->type = STGTY_STREAM;
262
+   stg->cbSize.QuadPart = (ULONGLONG)buf->size;
263
+
264
+   if (flag == STATFLAG_DEFAULT) {
265
+       stg->pwcsName = (wchar_t*)CoTaskMemAlloc(sizeof(stat_name));
266
+       memcpy(stg->pwcsName, stat_name, sizeof(stat_name));
267
+   }
268
+
269
+   return S_OK;
270
+}
271
+
272
+STDMETHODIMP CaptionStream::Clone(IStream **stream)
273
+{
274
+   debugfunc("stream");
275
+   *stream = nullptr;
276
+   return E_NOTIMPL;
277
+}
278
+
279
+// ISpStreamFormat methods
280
+
281
+STDMETHODIMP CaptionStream::GetFormat(GUID *guid,
282
+       WAVEFORMATEX **co_mem_wfex_out)
283
+{
284
+   debugfunc("guid, co_mem_wfex_out");
285
+
286
+   if (!guid || !co_mem_wfex_out)
287
+       return E_POINTER;
288
+
289
+   if (format.wFormatTag == 0) {
290
+       *co_mem_wfex_out = nullptr;
291
+       return S_OK;
292
+   }
293
+
294
+   void *wfex = CoTaskMemAlloc(sizeof(format));
295
+   memcpy(wfex, &format, sizeof(format));
296
+
297
+   *co_mem_wfex_out = (WAVEFORMATEX*)wfex;
298
+   return S_OK;
299
+}
300
+
301
+// ISpAudio methods
302
+
303
+STDMETHODIMP CaptionStream::SetState(SPAUDIOSTATE state_, ULONGLONG)
304
+{
305
+   debugfunc("%lu, reserved", state_);
306
+   state = state_;
307
+   return S_OK;
308
+}
309
+
310
+STDMETHODIMP CaptionStream::SetFormat(REFGUID guid_ref,
311
+       const WAVEFORMATEX *wfex)
312
+{
313
+   debugfunc("guid, wfex");
314
+   if (!wfex)
315
+       return E_INVALIDARG;
316
+
317
+   if (guid_ref == SPDFID_WaveFormatEx) {
318
+       lock_guard<mutex> lock(m);
319
+       memcpy(&format, wfex, sizeof(format));
320
+       resampler.Reset(wfex);
321
+
322
+       /* 50 msec */
323
+       DWORD size = format.nSamplesPerSec / 20;
324
+       DWORD byte_size = size * format.nBlockAlign;
325
+       circlebuf_reserve(buf, (size_t)byte_size);
326
+   }
327
+   return S_OK;
328
+}
329
+
330
+STDMETHODIMP CaptionStream::GetStatus(SPAUDIOSTATUS *status)
331
+{
332
+   debugfunc("status");
333
+
334
+   if (!status)
335
+       return E_POINTER;
336
+
337
+   /* TODO? */
338
+   lock_guard<mutex> lock(m);
339
+   *status = {};
340
+   status->cbNonBlockingIO = (ULONG)buf->size;
341
+   status->State = state;
342
+   status->CurSeekPos = pos.QuadPart;
343
+   status->CurDevicePos = write_pos;
344
+   return S_OK;
345
+}
346
+
347
+STDMETHODIMP CaptionStream::SetBufferInfo(const SPAUDIOBUFFERINFO *buf_info_)
348
+{
349
+   debugfunc("buf_info");
350
+
351
+   /* TODO */
352
+   buf_info = *buf_info_;
353
+   return S_OK;
354
+}
355
+
356
+STDMETHODIMP CaptionStream::GetBufferInfo(SPAUDIOBUFFERINFO *buf_info_)
357
+{
358
+   debugfunc("buf_info");
359
+   if (!buf_info_)
360
+       return E_POINTER;
361
+
362
+   *buf_info_ = buf_info;
363
+   return S_OK;
364
+}
365
+
366
+STDMETHODIMP CaptionStream::GetDefaultFormat(GUID *format,
367
+       WAVEFORMATEX **co_mem_wfex_out)
368
+{
369
+   debugfunc("format, co_mem_wfex_out");
370
+
371
+   if (!format || !co_mem_wfex_out)
372
+       return E_POINTER;
373
+
374
+   void *wfex = CoTaskMemAlloc(sizeof(format));
375
+   memcpy(wfex, &format, sizeof(format));
376
+
377
+   *format = SPDFID_WaveFormatEx;
378
+   *co_mem_wfex_out = (WAVEFORMATEX*)wfex;
379
+   return S_OK;
380
+}
381
+
382
+STDMETHODIMP_(HANDLE) CaptionStream::EventHandle(void)
383
+{
384
+   debugfunc("");
385
+   return event;
386
+}
387
+
388
+STDMETHODIMP CaptionStream::GetVolumeLevel(ULONG *level)
389
+{
390
+   debugfunc("level");
391
+   if (!level)
392
+       return E_POINTER;
393
+
394
+   *level = vol;
395
+   return S_OK;
396
+}
397
+
398
+STDMETHODIMP CaptionStream::SetVolumeLevel(ULONG level)
399
+{
400
+   debugfunc("%lu", level);
401
+   vol = level;
402
+   return S_OK;
403
+}
404
+
405
+STDMETHODIMP CaptionStream::GetBufferNotifySize(ULONG *size)
406
+{
407
+   debugfunc("size");
408
+   if (!size)
409
+       return E_POINTER;
410
+   *size = notify_size;
411
+   return S_OK;
412
+}
413
+
414
+STDMETHODIMP CaptionStream::SetBufferNotifySize(ULONG size)
415
+{
416
+   debugfunc("%lu", size);
417
+   notify_size = size;
418
+   return S_OK;
419
+}
420
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/captions-stream.hpp Added
121
 
1
@@ -0,0 +1,119 @@
2
+#include <windows.h>
3
+#include <sapi.h>
4
+#include <condition_variable>
5
+#include <mutex>
6
+#include <vector>
7
+#include <obs.h>
8
+#include <media-io/audio-resampler.h>
9
+#include <util/circlebuf.h>
10
+#include <util/windows/WinHandle.hpp>
11
+
12
+#include <fstream>
13
+
14
+class CircleBuf {
15
+   circlebuf buf = {};
16
+public:
17
+   inline ~CircleBuf() {circlebuf_free(&buf);}
18
+   inline operator circlebuf*() {return &buf;}
19
+   inline circlebuf *operator->() {return &buf;}
20
+};
21
+
22
+class Resampler {
23
+   audio_resampler_t *resampler = nullptr;
24
+
25
+public:
26
+   inline void Reset(const WAVEFORMATEX *wfex)
27
+   {
28
+       const struct audio_output_info *aoi =
29
+           audio_output_get_info(obs_get_audio());
30
+
31
+       struct resample_info src;
32
+       src.samples_per_sec = aoi->samples_per_sec;
33
+       src.format = aoi->format;
34
+       src.speakers = aoi->speakers;
35
+
36
+       struct resample_info dst;
37
+       dst.samples_per_sec = uint32_t(wfex->nSamplesPerSec);
38
+       dst.format = AUDIO_FORMAT_16BIT;
39
+       dst.speakers = (enum speaker_layout)wfex->nChannels;
40
+
41
+       if (resampler)
42
+           audio_resampler_destroy(resampler);
43
+       resampler = audio_resampler_create(&dst, &src);
44
+   }
45
+
46
+   inline ~Resampler() {audio_resampler_destroy(resampler);}
47
+   inline operator audio_resampler_t*() {return resampler;}
48
+};
49
+
50
+class CaptionStream : public ISpAudio {
51
+   volatile long refs = 1;
52
+   SPAUDIOBUFFERINFO buf_info = {};
53
+   ULONG notify_size = 0;
54
+   SPAUDIOSTATE state;
55
+   WinHandle event;
56
+   ULONG vol = 0;
57
+
58
+   std::condition_variable cv;
59
+   std::mutex m;
60
+   std::vector<int16_t> temp_buf;
61
+   WAVEFORMATEX format = {};
62
+   Resampler resampler;
63
+
64
+   CircleBuf buf;
65
+   ULONG wait_size = 0;
66
+   DWORD samplerate = 0;
67
+   ULARGE_INTEGER pos = {};
68
+   ULONGLONG write_pos = 0;
69
+
70
+public:
71
+   CaptionStream(DWORD samplerate);
72
+
73
+   void Stop();
74
+   void PushAudio(const struct audio_data *audio_data, bool muted);
75
+
76
+   // IUnknown methods
77
+   STDMETHODIMP QueryInterface(REFIID riid, void **ppv) override;
78
+   STDMETHODIMP_(ULONG) AddRef() override;
79
+   STDMETHODIMP_(ULONG) Release() override;
80
+
81
+   // ISequentialStream methods
82
+   STDMETHODIMP Read(void *data, ULONG bytes, ULONG *read_bytes) override;
83
+   STDMETHODIMP Write(const void *data, ULONG bytes, ULONG *written_bytes)
84
+       override;
85
+
86
+   // IStream methods
87
+   STDMETHODIMP Seek(LARGE_INTEGER move, DWORD origin,
88
+           ULARGE_INTEGER *new_pos) override;
89
+   STDMETHODIMP SetSize(ULARGE_INTEGER new_size) override;
90
+   STDMETHODIMP CopyTo(IStream *stream, ULARGE_INTEGER bytes,
91
+           ULARGE_INTEGER *read_bytes,
92
+           ULARGE_INTEGER *written_bytes) override;
93
+   STDMETHODIMP Commit(DWORD commit_flags) override;
94
+   STDMETHODIMP Revert(void) override;
95
+   STDMETHODIMP LockRegion(ULARGE_INTEGER offset, ULARGE_INTEGER size,
96
+           DWORD type) override;
97
+   STDMETHODIMP UnlockRegion(ULARGE_INTEGER offset, ULARGE_INTEGER size,
98
+           DWORD type) override;
99
+   STDMETHODIMP Stat(STATSTG *stg, DWORD flags) override;
100
+   STDMETHODIMP Clone(IStream **stream) override;
101
+
102
+   // ISpStreamFormat methods
103
+   STDMETHODIMP GetFormat(GUID *guid, WAVEFORMATEX **co_mem_wfex_out)
104
+       override;
105
+
106
+   // ISpAudio methods
107
+   STDMETHODIMP SetState(SPAUDIOSTATE state, ULONGLONG reserved) override;
108
+   STDMETHODIMP SetFormat(REFGUID guid_ref, const WAVEFORMATEX *wfex)
109
+       override;
110
+   STDMETHODIMP GetStatus(SPAUDIOSTATUS *status) override;
111
+   STDMETHODIMP SetBufferInfo(const SPAUDIOBUFFERINFO *buf_info) override;
112
+   STDMETHODIMP GetBufferInfo(SPAUDIOBUFFERINFO *buf_info) override;
113
+   STDMETHODIMP GetDefaultFormat(GUID *format,
114
+           WAVEFORMATEX **co_mem_wfex_out) override;
115
+   STDMETHODIMP_(HANDLE) EventHandle(void) override;
116
+   STDMETHODIMP GetVolumeLevel(ULONG *level) override;
117
+   STDMETHODIMP SetVolumeLevel(ULONG level) override;
118
+   STDMETHODIMP GetBufferNotifySize(ULONG *size) override;
119
+   STDMETHODIMP SetBufferNotifySize(ULONG size) override;
120
+};
121
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/captions.cpp Added
535
 
1
@@ -0,0 +1,533 @@
2
+#include <obs-frontend-api.h>
3
+#include "captions-stream.hpp"
4
+#include "captions.hpp"
5
+#include "tool-helpers.hpp"
6
+#include <sphelper.h>
7
+#include <util/dstr.hpp>
8
+#include <util/platform.h>
9
+#include <util/windows/HRError.hpp>
10
+#include <util/windows/ComPtr.hpp>
11
+#include <util/windows/CoTaskMemPtr.hpp>
12
+#include <util/threading.h>
13
+#include <obs-module.h>
14
+
15
+#include <string>
16
+#include <thread>
17
+#include <mutex>
18
+
19
+#define do_log(type, format, ...) blog(type, "[Captions] " format, \
20
+       ##__VA_ARGS__)
21
+
22
+#define error(format, ...) do_log(LOG_ERROR, format, ##__VA_ARGS__)
23
+#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
24
+
25
+using namespace std;
26
+
27
+struct obs_captions {
28
+   thread th;
29
+   recursive_mutex m;
30
+   WinHandle stop_event;
31
+
32
+   string source_name;
33
+   OBSWeakSource source;
34
+   LANGID lang_id;
35
+
36
+   void main_thread();
37
+   void start();
38
+   void stop();
39
+
40
+   inline obs_captions() :
41
+       stop_event(CreateEvent(nullptr, false, false, nullptr)),
42
+       lang_id(GetUserDefaultUILanguage())
43
+   {
44
+   }
45
+
46
+   inline ~obs_captions() {stop();}
47
+};
48
+
49
+static obs_captions *captions = nullptr;
50
+
51
+/* ------------------------------------------------------------------------- */
52
+
53
+struct locale_info {
54
+   DStr name;
55
+   LANGID id;
56
+
57
+   inline locale_info() {}
58
+   inline locale_info(const locale_info &) = delete;
59
+   inline locale_info(locale_info &&li)
60
+       : name(std::move(li.name)),
61
+         id(li.id)
62
+   {}
63
+};
64
+
65
+static void get_valid_locale_names(vector<locale_info> &names);
66
+static bool valid_lang(LANGID id);
67
+
68
+/* ------------------------------------------------------------------------- */
69
+
70
+CaptionsDialog::CaptionsDialog(QWidget *parent) :
71
+   QDialog(parent),
72
+   ui(new Ui_CaptionsDialog)
73
+{
74
+   ui->setupUi(this);
75
+
76
+   lock_guard<recursive_mutex> lock(captions->m);
77
+
78
+   auto cb = [this] (obs_source_t *source)
79
+   {
80
+       uint32_t caps = obs_source_get_output_flags(source);
81
+       QString name = obs_source_get_name(source);
82
+
83
+       if (caps & OBS_SOURCE_AUDIO)
84
+           ui->source->addItem(name);
85
+
86
+       OBSWeakSource weak = OBSGetWeakRef(source);
87
+       if (weak == captions->source)
88
+           ui->source->setCurrentText(name);
89
+       return true;
90
+   };
91
+
92
+   using cb_t = decltype(cb);
93
+
94
+   ui->source->blockSignals(true);
95
+   ui->source->addItem(QStringLiteral(""));
96
+   ui->source->setCurrentIndex(0);
97
+   obs_enum_sources([] (void *data, obs_source_t *source) {
98
+           return (*static_cast<cb_t*>(data))(source);}, &cb);
99
+   ui->source->blockSignals(false);
100
+
101
+   ui->enable->blockSignals(true);
102
+   ui->enable->setChecked(captions->th.joinable());
103
+   ui->enable->blockSignals(false);
104
+
105
+   vector<locale_info> locales;
106
+   get_valid_locale_names(locales);
107
+
108
+   bool set_language = false;
109
+
110
+   ui->language->blockSignals(true);
111
+   for (int idx = 0; idx < (int)locales.size(); idx++) {
112
+       locale_info &locale = locales[idx];
113
+
114
+       ui->language->addItem(locale.name->array, (int)locale.id);
115
+
116
+       if (locale.id == captions->lang_id) {
117
+           ui->language->setCurrentIndex(idx);
118
+           set_language = true;
119
+       }
120
+   }
121
+
122
+   if (!set_language && locales.size())
123
+       ui->language->setCurrentIndex(0);
124
+
125
+   ui->language->blockSignals(false);
126
+
127
+   if (!locales.size()) {
128
+       ui->source->setEnabled(false);
129
+       ui->enable->setEnabled(false);
130
+       ui->language->setEnabled(false);
131
+
132
+   } else if (!set_language) {
133
+       bool started = captions->th.joinable();
134
+       if (started)
135
+           captions->stop();
136
+
137
+       captions->m.lock();
138
+       captions->lang_id = locales[0].id;
139
+       captions->m.unlock();
140
+
141
+       if (started)
142
+           captions->start();
143
+   }
144
+}
145
+
146
+void CaptionsDialog::on_source_currentIndexChanged(int)
147
+{
148
+   bool started = captions->th.joinable();
149
+   if (started)
150
+       captions->stop();
151
+
152
+   captions->m.lock();
153
+   captions->source_name = ui->source->currentText().toUtf8().constData();
154
+   captions->source = GetWeakSourceByName(captions->source_name.c_str());
155
+   captions->m.unlock();
156
+
157
+   if (started)
158
+       captions->start();
159
+}
160
+
161
+void CaptionsDialog::on_enable_clicked(bool checked)
162
+{
163
+   if (checked)
164
+       captions->start();
165
+   else
166
+       captions->stop();
167
+}
168
+
169
+void CaptionsDialog::on_language_currentIndexChanged(int)
170
+{
171
+   bool started = captions->th.joinable();
172
+   if (started)
173
+       captions->stop();
174
+
175
+   captions->m.lock();
176
+   captions->lang_id = (LANGID)ui->language->currentData().toInt();
177
+   captions->m.unlock();
178
+
179
+   if (started)
180
+       captions->start();
181
+}
182
+
183
+/* ------------------------------------------------------------------------- */
184
+
185
+void obs_captions::main_thread()
186
+try {
187
+   ComPtr<CaptionStream>  audio;
188
+   ComPtr<ISpObjectToken> token;
189
+   ComPtr<ISpRecoGrammar> grammar;
190
+   ComPtr<ISpRecognizer>  recognizer;
191
+   ComPtr<ISpRecoContext> context;
192
+   HRESULT hr;
193
+
194
+   auto cb = [&] (const struct audio_data *audio_data,
195
+           bool muted)
196
+   {
197
+       audio->PushAudio(audio_data, muted);
198
+   };
199
+
200
+   using cb_t = decltype(cb);
201
+
202
+   auto pre_cb = [] (void *param, obs_source_t*,
203
+       const struct audio_data *audio_data, bool muted)
204
+   {
205
+       return (*static_cast<cb_t*>(param))(audio_data, muted);
206
+   };
207
+
208
+   os_set_thread_name(__FUNCTION__);
209
+
210
+   CoInitialize(nullptr);
211
+
212
+   wchar_t lang_str[32];
213
+   _snwprintf(lang_str, 31, L"language=%x", (int)captions->lang_id);
214
+
215
+   hr = SpFindBestToken(SPCAT_RECOGNIZERS, lang_str, nullptr, &token);
216
+   if (FAILED(hr))
217
+       throw HRError("SpFindBestToken failed", hr);
218
+
219
+   hr = CoCreateInstance(CLSID_SpInprocRecognizer, nullptr, CLSCTX_ALL,
220
+           __uuidof(ISpRecognizer), (void**)&recognizer);
221
+   if (FAILED(hr))
222
+       throw HRError("CoCreateInstance for recognizer failed", hr);
223
+
224
+   hr = recognizer->SetRecognizer(token);
225
+   if (FAILED(hr))
226
+       throw HRError("SetRecognizer failed", hr);
227
+
228
+   hr = recognizer->SetRecoState(SPRST_INACTIVE);
229
+   if (FAILED(hr))
230
+       throw HRError("SetRecoState(SPRST_INACTIVE) failed", hr);
231
+
232
+   hr = recognizer->CreateRecoContext(&context);
233
+   if (FAILED(hr))
234
+       throw HRError("CreateRecoContext failed", hr);
235
+
236
+   ULONGLONG interest = SPFEI(SPEI_RECOGNITION) |
237
+       SPFEI(SPEI_END_SR_STREAM);
238
+   hr = context->SetInterest(interest, interest);
239
+   if (FAILED(hr))
240
+       throw HRError("SetInterest failed", hr);
241
+
242
+   HANDLE notify;
243
+
244
+   hr = context->SetNotifyWin32Event();
245
+   if (FAILED(hr))
246
+       throw HRError("SetNotifyWin32Event", hr);
247
+
248
+   notify = context->GetNotifyEventHandle();
249
+   if (notify == INVALID_HANDLE_VALUE)
250
+       throw HRError("GetNotifyEventHandle failed", E_NOINTERFACE);
251
+
252
+   size_t sample_rate = audio_output_get_sample_rate(obs_get_audio());
253
+   audio = new CaptionStream((DWORD)sample_rate);
254
+   audio->Release();
255
+
256
+   hr = recognizer->SetInput(audio, false);
257
+   if (FAILED(hr))
258
+       throw HRError("SetInput failed", hr);
259
+
260
+   hr = context->CreateGrammar(1, &grammar);
261
+   if (FAILED(hr))
262
+       throw HRError("CreateGrammar failed", hr);
263
+
264
+   hr = grammar->LoadDictation(nullptr, SPLO_STATIC);
265
+   if (FAILED(hr))
266
+       throw HRError("LoadDictation failed", hr);
267
+
268
+   hr = grammar->SetDictationState(SPRS_ACTIVE);
269
+   if (FAILED(hr))
270
+       throw HRError("SetDictationState failed", hr);
271
+
272
+   hr = recognizer->SetRecoState(SPRST_ACTIVE);
273
+   if (FAILED(hr))
274
+       throw HRError("SetRecoState(SPRST_ACTIVE) failed", hr);
275
+
276
+   HANDLE events[] = {notify, stop_event};
277
+
278
+   {
279
+       captions->source = GetWeakSourceByName(
280
+               captions->source_name.c_str());
281
+       OBSSource strong = OBSGetStrongRef(source);
282
+       if (strong)
283
+           obs_source_add_audio_capture_callback(strong,
284
+                   pre_cb, &cb);
285
+   }
286
+
287
+   for (;;) {
288
+       DWORD ret = WaitForMultipleObjects(2, events, false, INFINITE);
289
+       if (ret != WAIT_OBJECT_0)
290
+           break;
291
+
292
+       CSpEvent event;
293
+       bool exit = false;
294
+
295
+       while (event.GetFrom(context) == S_OK) {
296
+           if (event.eEventId == SPEI_RECOGNITION) {
297
+               ISpRecoResult *result = event.RecoResult();
298
+
299
+               CoTaskMemPtr<wchar_t> text;
300
+               hr = result->GetText((ULONG)-1, (ULONG)-1,
301
+                       true, &text, nullptr);
302
+               if (FAILED(hr))
303
+                   continue;
304
+
305
+               char text_utf8[512];
306
+               os_wcs_to_utf8(text, 0, text_utf8, 512);
307
+
308
+               obs_output_t *output =
309
+                   obs_frontend_get_streaming_output();
310
+               if (output)
311
+                   obs_output_output_caption_text1(output,
312
+                           text_utf8);
313
+
314
+               debug("\"%s\"", text_utf8);
315
+
316
+               obs_output_release(output);
317
+
318
+           } else if (event.eEventId == SPEI_END_SR_STREAM) {
319
+               exit = true;
320
+               break;
321
+           }
322
+       }
323
+
324
+       if (exit)
325
+           break;
326
+   }
327
+
328
+   {
329
+       OBSSource strong = OBSGetStrongRef(source);
330
+       if (strong)
331
+           obs_source_remove_audio_capture_callback(strong,
332
+                   pre_cb, &cb);
333
+   }
334
+
335
+   audio->Stop();
336
+
337
+   CoUninitialize();
338
+
339
+} catch (HRError err) {
340
+   error("%s failed: %s (%lX)", __FUNCTION__, err.str, err.hr);
341
+   CoUninitialize();
342
+   captions->th.detach();
343
+}
344
+
345
+void obs_captions::start()
346
+{
347
+   if (!captions->th.joinable()) {
348
+       ResetEvent(captions->stop_event);
349
+
350
+       if (valid_lang(captions->lang_id))
351
+           captions->th = thread([] () {captions->main_thread();});
352
+   }
353
+}
354
+
355
+void obs_captions::stop()
356
+{
357
+   if (!captions->th.joinable())
358
+       return;
359
+
360
+   SetEvent(captions->stop_event);
361
+   captions->th.join();
362
+}
363
+
364
+static bool get_locale_name(LANGID id, char *out)
365
+{
366
+   wchar_t name[256];
367
+
368
+   int size = GetLocaleInfoW(id, LOCALE_SENGLISHLANGUAGENAME, name, 256);
369
+   if (size <= 0)
370
+       return false;
371
+
372
+   os_wcs_to_utf8(name, 0, out, 256);
373
+   return true;
374
+}
375
+
376
+static bool valid_lang(LANGID id)
377
+{
378
+   ComPtr<ISpObjectToken> token;
379
+   wchar_t lang_str[32];
380
+   HRESULT hr;
381
+
382
+   _snwprintf(lang_str, 31, L"language=%x", (int)id);
383
+
384
+   hr = SpFindBestToken(SPCAT_RECOGNIZERS, lang_str, nullptr, &token);
385
+   return SUCCEEDED(hr);
386
+}
387
+
388
+static void get_valid_locale_names(vector<locale_info> &locales)
389
+{
390
+   locale_info cur;
391
+   char locale_name[256];
392
+
393
+   static const LANGID default_locales[] = {
394
+       0x0409,
395
+       0x0401,
396
+       0x0402,
397
+       0x0403,
398
+       0x0404,
399
+       0x0405,
400
+       0x0406,
401
+       0x0407,
402
+       0x0408,
403
+       0x040a,
404
+       0x040b,
405
+       0x040c,
406
+       0x040d,
407
+       0x040e,
408
+       0x040f,
409
+       0x0410,
410
+       0x0411,
411
+       0x0412,
412
+       0x0413,
413
+       0x0414,
414
+       0x0415,
415
+       0x0416,
416
+       0x0417,
417
+       0x0418,
418
+       0x0419,
419
+       0x041a,
420
+       0
421
+   };
422
+
423
+   /* ---------------------------------- */
424
+
425
+   LANGID def_id = GetUserDefaultUILanguage();
426
+   LANGID id = def_id;
427
+   if (valid_lang(id) && get_locale_name(id, locale_name)) {
428
+       dstr_copy(cur.name, obs_module_text(
429
+                   "Captions.CurrentSystemLanguage"));
430
+       dstr_replace(cur.name, "%1", locale_name);
431
+       cur.id = id;
432
+
433
+       locales.push_back(std::move(cur));
434
+   }
435
+
436
+   /* ---------------------------------- */
437
+
438
+   const LANGID *locale = default_locales;
439
+
440
+   while (*locale) {
441
+       id = *locale;
442
+
443
+       if (id != def_id &&
444
+           valid_lang(id) &&
445
+           get_locale_name(id, locale_name)) {
446
+
447
+           dstr_copy(cur.name, locale_name);
448
+           cur.id = id;
449
+
450
+           locales.push_back(std::move(cur));
451
+       }
452
+
453
+       locale++;
454
+   }
455
+}
456
+
457
+/* ------------------------------------------------------------------------- */
458
+
459
+extern "C" void FreeCaptions()
460
+{
461
+   delete captions;
462
+   captions = nullptr;
463
+}
464
+
465
+static void obs_event(enum obs_frontend_event event, void *)
466
+{
467
+   if (event == OBS_FRONTEND_EVENT_EXIT)
468
+       FreeCaptions();
469
+}
470
+
471
+static void save_caption_data(obs_data_t *save_data, bool saving, void*)
472
+{
473
+   if (saving) {
474
+       lock_guard<recursive_mutex> lock(captions->m);
475
+       obs_data_t *obj = obs_data_create();
476
+
477
+       obs_data_set_string(obj, "source",
478
+               captions->source_name.c_str());
479
+       obs_data_set_bool(obj, "enabled", captions->th.joinable());
480
+       obs_data_set_int(obj, "lang_id", captions->lang_id);
481
+
482
+       obs_data_set_obj(save_data, "captions", obj);
483
+       obs_data_release(obj);
484
+   } else {
485
+       captions->stop();
486
+
487
+       captions->m.lock();
488
+
489
+       obs_data_t *obj = obs_data_get_obj(save_data, "captions");
490
+       if (!obj)
491
+           obj = obs_data_create();
492
+
493
+       obs_data_set_default_int(obj, "lang_id",
494
+               GetUserDefaultUILanguage());
495
+
496
+       bool enabled = obs_data_get_bool(obj, "enabled");
497
+       captions->source_name = obs_data_get_string(obj, "source");
498
+       captions->lang_id = (int)obs_data_get_int(obj, "lang_id");
499
+       captions->source = GetWeakSourceByName(
500
+               captions->source_name.c_str());
501
+       obs_data_release(obj);
502
+
503
+       captions->m.unlock();
504
+
505
+       if (enabled)
506
+           captions->start();
507
+   }
508
+}
509
+
510
+extern "C" void InitCaptions()
511
+{
512
+   QAction *action = (QAction*)obs_frontend_add_tools_menu_qaction(
513
+           obs_module_text("Captions"));
514
+
515
+   captions = new obs_captions;
516
+
517
+   auto cb = [] ()
518
+   {
519
+       obs_frontend_push_ui_translation(obs_module_get_string);
520
+
521
+       QWidget *window =
522
+           (QWidget*)obs_frontend_get_main_window();
523
+
524
+       CaptionsDialog dialog(window);
525
+       dialog.exec();
526
+
527
+       obs_frontend_pop_ui_translation();
528
+   };
529
+
530
+   obs_frontend_add_save_callback(save_caption_data, nullptr);
531
+   obs_frontend_add_event_callback(obs_event, nullptr);
532
+
533
+   action->connect(action, &QAction::triggered, cb);
534
+}
535
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/captions.hpp Added
22
 
1
@@ -0,0 +1,20 @@
2
+#pragma once
3
+
4
+#include <QDialog>
5
+#include <memory>
6
+
7
+#include "ui_captions.h"
8
+
9
+class CaptionsDialog : public QDialog {
10
+   Q_OBJECT
11
+
12
+   std::unique_ptr<Ui_CaptionsDialog> ui;
13
+
14
+public:
15
+   CaptionsDialog(QWidget *parent);
16
+
17
+public slots:
18
+   void on_source_currentIndexChanged(int idx);
19
+   void on_enable_clicked(bool checked);
20
+   void on_language_currentIndexChanged(int idx);
21
+};
22
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ca-ES.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ca-ES.ini Changed
9
 
1
@@ -11,6 +11,7 @@
2
 Start="Inicia"
3
 Stop="Atura"
4
 
5
+
6
 OutputTimer="Temporitzador de sortida"
7
 OutputTimer.Stream="Atura la transmissió després de:"
8
 OutputTimer.Record="Atura la gravació després de:"
9
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/cs-CZ.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/cs-CZ.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="Spustit"
3
 Stop="Zastavit"
4
 
5
+
6
 OutputTimer="Časovač"
7
 OutputTimer.Stream="Přestat vysílat po:"
8
 OutputTimer.Record="Přestat nahrávat po:"
9
 OutputTimer.Stream.StoppingIn="Vysílání se zastaví za:"
10
 OutputTimer.Record.StoppingIn="Nahrávání se zastaví za:"
11
+OutputTimer.Stream.EnableEverytime="Pokaždé povolit časovač vysílání"
12
+OutputTimer.Record.EnableEverytime="Pokaždé povolit časovač nahrávání"
13
 
14
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/da-DK.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/da-DK.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="Start"
3
 Stop="Stop"
4
 
5
+
6
 OutputTimer="Output-timer"
7
 OutputTimer.Stream="Stands streaming efter:"
8
 OutputTimer.Record="Stands optagelse efter:"
9
 OutputTimer.Stream.StoppingIn="Streaming standser om:"
10
 OutputTimer.Record.StoppingIn="Streaming standser om:"
11
+OutputTimer.Stream.EnableEverytime="Aktivér streaming-timer hver gang"
12
+OutputTimer.Record.EnableEverytime="Aktivér optage-timer hver gang"
13
 
14
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/de-DE.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/de-DE.ini Changed
16
 
1
@@ -11,9 +11,14 @@
2
 Start="Start"
3
 Stop="Stop"
4
 
5
+Captions="Untertitel (experimentell)"
6
+Captions.AudioSource="Audioquelle:"
7
+
8
 OutputTimer="Ausgabetimer"
9
 OutputTimer.Stream="Stoppe Stream nach:"
10
 OutputTimer.Record="Stoppe Aufnahme nach:"
11
 OutputTimer.Stream.StoppingIn="Stream stoppt in:"
12
 OutputTimer.Record.StoppingIn="Aufnahme stoppt in:"
13
+OutputTimer.Stream.EnableEverytime="Streaming-Timer jedes Mal aktivieren"
14
+OutputTimer.Record.EnableEverytime="Aufnahme-Timer jedes Mal aktivieren"
15
 
16
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/en-US.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/en-US.ini Changed
16
 
1
@@ -11,8 +11,14 @@
2
 Start="Start"
3
 Stop="Stop"
4
 
5
+Captions="Captions (Experimental)"
6
+Captions.AudioSource="Audio source"
7
+Captions.CurrentSystemLanguage="Current System Language (%1)"
8
+
9
 OutputTimer="Output Timer"
10
 OutputTimer.Stream="Stop streaming after:"
11
 OutputTimer.Record="Stop recording after:"
12
 OutputTimer.Stream.StoppingIn="Streaming stopping in:"
13
 OutputTimer.Record.StoppingIn="Recording stopping in:"
14
+OutputTimer.Stream.EnableEverytime="Enable streaming timer every time"
15
+OutputTimer.Record.EnableEverytime="Enable recording timer every time"
16
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/es-ES.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/es-ES.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="Iniciar"
3
 Stop="Detener"
4
 
5
+
6
 OutputTimer="Temporizador de salida"
7
 OutputTimer.Stream="Detener la transmisión después de:"
8
 OutputTimer.Record="Detener la grabación después de:"
9
 OutputTimer.Stream.StoppingIn="Finalizando transmisión en:"
10
 OutputTimer.Record.StoppingIn="Finalizando grabación en:"
11
+OutputTimer.Stream.EnableEverytime="Activar temporizador en cada transmisión"
12
+OutputTimer.Record.EnableEverytime="Activar temporizador en cada grabación"
13
 
14
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/eu-ES.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/eu-ES.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="Hasi"
3
 Stop="Gelditu"
4
 
5
+
6
 OutputTimer="Irteera tenporizadorea"
7
 OutputTimer.Stream="Gelditu transmisioa hau pasata:"
8
 OutputTimer.Record="Gelditu grabazioa hau pasata:"
9
 OutputTimer.Stream.StoppingIn="Transmisioa geldituko da: hau barru:"
10
 OutputTimer.Record.StoppingIn="Grabazioa geldituko da hau barru:"
11
+OutputTimer.Stream.EnableEverytime="Gaitu transmisio tenporizadorea aldiro"
12
+OutputTimer.Record.EnableEverytime="Gaitu grabazio tenporizadorea aldiro"
13
 
14
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/fi-FI.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/fi-FI.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="Käynnistä"
3
 Stop="Pysäytä"
4
 
5
+
6
 OutputTimer="Ulostulo-ajastin"
7
 OutputTimer.Stream="Pysäyttää lähetyksen:"
8
 OutputTimer.Record="Pysäyttää tallennuksen:"
9
 OutputTimer.Stream.StoppingIn="Lähetys pysäytetään:"
10
 OutputTimer.Record.StoppingIn="Tallennus pysäytetään:"
11
+OutputTimer.Stream.EnableEverytime="Ota lähetysajastin käyttöön aina"
12
+OutputTimer.Record.EnableEverytime="Ota tallennusajastin käyttöön aina"
13
 
14
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/fr-FR.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/fr-FR.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="Démarrer"
3
 Stop="Arrêter"
4
 
5
+
6
 OutputTimer="Minuterie des sorties"
7
 OutputTimer.Stream="Arrêter le streaming dans :"
8
 OutputTimer.Record="Arrêter l'enregistrement dans :"
9
 OutputTimer.Stream.StoppingIn="Arrêt du streaming dans :"
10
 OutputTimer.Record.StoppingIn="Arrêt de l'enregistrement dans :"
11
+OutputTimer.Stream.EnableEverytime="Activer le minuteur automatiquement à chaque stream"
12
+OutputTimer.Record.EnableEverytime="Activer le minuteur automatiquement à chaque enregistrement"
13
 
14
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/hr-HR.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/hr-HR.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="Pokreni"
3
 Stop="Zaustavi"
4
 
5
+
6
 OutputTimer="Tempomat snimanja i emitovanja"
7
 OutputTimer.Stream="Zaustavi emitovanje nakon:"
8
 OutputTimer.Record="Zaustavi snimanje nakon:"
9
 OutputTimer.Stream.StoppingIn="Prekidanje emitovanja za:"
10
 OutputTimer.Record.StoppingIn="Prekidanje snimanja za:"
11
+OutputTimer.Stream.EnableEverytime="Omogući štopovanje emitovanja svaki put"
12
+OutputTimer.Record.EnableEverytime="Omogući štopovanje snimanja svaki put"
13
 
14
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/hu-HU.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/hu-HU.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="Start"
3
 Stop="Stop"
4
 
5
+
6
 OutputTimer="Kimeneti időzítő"
7
 OutputTimer.Stream="Stream leállítása:"
8
 OutputTimer.Record="Felvétel leállítása:"
9
 OutputTimer.Stream.StoppingIn="A stream leáll:"
10
 OutputTimer.Record.StoppingIn="Felvétel leáll:"
11
+OutputTimer.Stream.EnableEverytime="Stream időzítő indítása minden alkalommal"
12
+OutputTimer.Record.EnableEverytime="Felvétel időzítő indítása minden alkalommal"
13
 
14
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/it-IT.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/it-IT.ini Changed
9
 
1
@@ -11,6 +11,7 @@
2
 Start="Inizio"
3
 Stop="Stop"
4
 
5
+
6
 OutputTimer="Timer Output"
7
 OutputTimer.Stream="Termina diretta dopo:"
8
 OutputTimer.Record="Termina registrazione dopo:"
9
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ja-JP.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ja-JP.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="開始"
3
 Stop="停止"
4
 
5
+
6
 OutputTimer="出力タイマー"
7
 OutputTimer.Stream="配信停止の時間設定:"
8
 OutputTimer.Record="録画停止の時間設定:"
9
 OutputTimer.Stream.StoppingIn="配信停止まで:"
10
 OutputTimer.Record.StoppingIn="録画停止まで:"
11
+OutputTimer.Stream.EnableEverytime="毎回配信タイマーを有効にする"
12
+OutputTimer.Record.EnableEverytime="毎回録画タイマーを有効にする"
13
 
14
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ko-KR.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ko-KR.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="시작"
3
 Stop="중단"
4
 
5
+
6
 OutputTimer="출력 시간 설정"
7
 OutputTimer.Stream="이 시간 이후 방송 중단:"
8
 OutputTimer.Record="이 시간 이후 녹화 중단:"
9
 OutputTimer.Stream.StoppingIn="방송 중지까지 남은 시간:"
10
 OutputTimer.Record.StoppingIn="녹화 중지까지 남은 시간:"
11
+OutputTimer.Stream.EnableEverytime="매번 방송 시간 기록기 활성화"
12
+OutputTimer.Record.EnableEverytime="매번 녹화 시간 기록기 활성화"
13
 
14
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ms-MY.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ms-MY.ini Changed
9
 
1
@@ -3,6 +3,7 @@
2
 Start="Mula"
3
 Stop="Berhenti"
4
 
5
+
6
 OutputTimer.Stream="Berhenti 'streaming' selepas:"
7
 OutputTimer.Record="Berhenti merakam selepas:"
8
 OutputTimer.Stream.StoppingIn="'Streaming' dihentikan dalam:"
9
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/nb-NO.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/nb-NO.ini Changed
6
 
1
@@ -5,3 +5,4 @@
2
 Stop="Stopp"
3
 
4
 
5
+
6
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/nl-NL.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/nl-NL.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="Start"
3
 Stop="Stop"
4
 
5
+
6
 OutputTimer="Uitvoertimer"
7
 OutputTimer.Stream="Stop met streamen na:"
8
 OutputTimer.Record="Stop met opnemen na:"
9
 OutputTimer.Stream.StoppingIn="Stream stopt over:"
10
 OutputTimer.Record.StoppingIn="Opname stopt over:"
11
+OutputTimer.Stream.EnableEverytime="Schakel streaming timer elke keer in"
12
+OutputTimer.Record.EnableEverytime="Schakel opnametimer elke keer in"
13
 
14
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/pl-PL.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/pl-PL.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="Start"
3
 Stop="Stop"
4
 
5
+
6
 OutputTimer="Wyłącznik czasowy"
7
 OutputTimer.Stream="Zatrzymaj stream po:"
8
 OutputTimer.Record="Zatrzymaj nagrywanie po:"
9
 OutputTimer.Stream.StoppingIn="Zatrzymanie streamu za:"
10
 OutputTimer.Record.StoppingIn="Zatrzymanie nagrywania za:"
11
+OutputTimer.Stream.EnableEverytime="Włącz timer streamu za każdym razem"
12
+OutputTimer.Record.EnableEverytime="Włącz timer nagrywania za każdym razem"
13
 
14
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/pt-BR.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/pt-BR.ini Changed
9
 
1
@@ -11,6 +11,7 @@
2
 Start="Iniciar"
3
 Stop="Parar"
4
 
5
+
6
 OutputTimer="Temporizador de saída"
7
 OutputTimer.Stream="Parar a transmissão após:"
8
 OutputTimer.Record="Parar a gravação após:"
9
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/pt-PT.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/pt-PT.ini Changed
9
 
1
@@ -11,6 +11,7 @@
2
 Start="Iniciar"
3
 Stop="Parar"
4
 
5
+
6
 OutputTimer="Temporizador de saída"
7
 OutputTimer.Stream="Para a transmissão após:"
8
 OutputTimer.Record="Parar a gravação após:"
9
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ru-RU.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ru-RU.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="Запустить"
3
 Stop="Остановить"
4
 
5
+
6
 OutputTimer="Таймер записи и стрима"
7
 OutputTimer.Stream="Завершить стрим через:"
8
 OutputTimer.Record="Завершить запись через:"
9
 OutputTimer.Stream.StoppingIn="Стрим будет завершён через:"
10
 OutputTimer.Record.StoppingIn="Запись будет завершена через:"
11
+OutputTimer.Stream.EnableEverytime="Включать таймер стрима каждый раз"
12
+OutputTimer.Record.EnableEverytime="Включать таймер записи каждый раз"
13
 
14
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/sk-SK.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/sk-SK.ini Changed
9
 
1
@@ -4,6 +4,7 @@
2
 Start="Spustiť"
3
 Stop="Zastaviť"
4
 
5
+
6
 OutputTimer.Stream="Zastaviť stream po:"
7
 OutputTimer.Record="Zastaviť nahrávanie po:"
8
 
9
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/sr-CS.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/sr-CS.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="Pokreni"
3
 Stop="Zaustavi"
4
 
5
+
6
 OutputTimer="Tempomat snimanja i emitovanja"
7
 OutputTimer.Stream="Zaustavi emitovanje nakon:"
8
 OutputTimer.Record="Zaustavi snimanje nakon:"
9
 OutputTimer.Stream.StoppingIn="Prekidanje emitovanja za:"
10
 OutputTimer.Record.StoppingIn="Prekidanje snimanja za:"
11
+OutputTimer.Stream.EnableEverytime="Omogući štopovanje emitovanja svaki put"
12
+OutputTimer.Record.EnableEverytime="Omogući štopovanje snimanja svaki put"
13
 
14
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/sr-SP.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/sr-SP.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="Покрени"
3
 Stop="Заустави"
4
 
5
+
6
 OutputTimer="Темпомат снимања и емитовања"
7
 OutputTimer.Stream="Заустави емитовање након:"
8
 OutputTimer.Record="Заустави снимање након:"
9
 OutputTimer.Stream.StoppingIn="Прекидање емитовања за:"
10
 OutputTimer.Record.StoppingIn="Прекидање снимања за:"
11
+OutputTimer.Stream.EnableEverytime="Омогући штоповање емитовање сваки пут"
12
+OutputTimer.Record.EnableEverytime="Омогући штоповање снимања сваки пут"
13
 
14
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/sv-SE.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/sv-SE.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="Starta"
3
 Stop="Stoppa"
4
 
5
+
6
 OutputTimer="Utdatatimer"
7
 OutputTimer.Stream="Sluta streama efter:"
8
 OutputTimer.Record="Stoppa inspelningen efter:"
9
 OutputTimer.Stream.StoppingIn="Streamen stoppas om:"
10
 OutputTimer.Record.StoppingIn="Inspelningen stoppas om:"
11
+OutputTimer.Stream.EnableEverytime="Aktivera strömtimer varje gång"
12
+OutputTimer.Record.EnableEverytime="Aktivera inspelningstimer varje gång"
13
 
14
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/tr-TR.ini Added
19
 
1
@@ -0,0 +1,17 @@
2
+SceneSwitcher="Otomatik Sahne Değiştirici"
3
+SceneSwitcher.OnNoMatch.DontSwitch="Geçiş yapma"
4
+SceneSwitcher.OnNoMatch.SwitchTo="Şuna geç:"
5
+SceneSwitcher.CheckInterval="Etkin pencere başlığını kontrol et:"
6
+SceneSwitcher.ActiveOrNotActive="Sahne Değiştirici:"
7
+Active="Etkin"
8
+Inactive="Devre Dışı"
9
+Start="Başlat"
10
+Stop="Durdur"
11
+
12
+
13
+OutputTimer="Çıkış Zamanlayıcısı"
14
+OutputTimer.Stream="Şuradan sonra yayını durdur:"
15
+OutputTimer.Record="Şuradan sonra kaydı durdur:"
16
+OutputTimer.Stream.EnableEverytime="Her zaman yayın zamanlayıcıyı etkinleştir"
17
+OutputTimer.Record.EnableEverytime="Her zaman kayıt zamanlayıcıyı etkinleştir"
18
+
19
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/uk-UA.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/uk-UA.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="Запустити"
3
 Stop="Зупинити"
4
 
5
+
6
 OutputTimer="Таймер для Виводу"
7
 OutputTimer.Stream="Закінчити трансляцію за:"
8
 OutputTimer.Record="Зупинити запис за:"
9
 OutputTimer.Stream.StoppingIn="Трансляція припиниться за:"
10
 OutputTimer.Record.StoppingIn="Запис зупиниться за:"
11
+OutputTimer.Stream.EnableEverytime="Щоразу запускається трансляція - вмикати Таймер для Виводу"
12
+OutputTimer.Record.EnableEverytime="Щоразу починається запис - вмикати Таймер для Виводу"
13
 
14
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/vi-VN.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/vi-VN.ini Changed
9
 
1
@@ -9,6 +9,7 @@
2
 Start="Bắt đầu"
3
 Stop="Dừng"
4
 
5
+
6
 OutputTimer.Stream="Dừng stream sau:"
7
 OutputTimer.Record="Dừng ghi video sau:"
8
 OutputTimer.Stream.StoppingIn="Stream sẽ dừng trong:"
9
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/zh-CN.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/zh-CN.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="开始"
3
 Stop="停止"
4
 
5
+
6
 OutputTimer="输出计时器"
7
 OutputTimer.Stream="停止流处理后:"
8
 OutputTimer.Record="停止录制后:"
9
 OutputTimer.Stream.StoppingIn="串流停止在:"
10
 OutputTimer.Record.StoppingIn="录制停止在:"
11
+OutputTimer.Stream.EnableEverytime="每次启用流计时器"
12
+OutputTimer.Record.EnableEverytime="每次启用录制计时器"
13
 
14
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/zh-TW.ini -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/zh-TW.ini Changed
14
 
1
@@ -11,9 +11,12 @@
2
 Start="開始"
3
 Stop="停止"
4
 
5
+
6
 OutputTimer="輸出計時器"
7
 OutputTimer.Stream="在下面時間後停止串流:"
8
 OutputTimer.Record="在下面時間後停止錄影:"
9
 OutputTimer.Stream.StoppingIn="串流將在下面時間內停止"
10
 OutputTimer.Record.StoppingIn="錄影將在下面時間內停止"
11
+OutputTimer.Stream.EnableEverytime="每次都啟動串流計時器"
12
+OutputTimer.Record.EnableEverytime="每次都啟動錄影計時器"
13
 
14
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/forms/captions.ui Added
134
 
1
@@ -0,0 +1,132 @@
2
+<?xml version="1.0" encoding="UTF-8"?>
3
+<ui version="4.0">
4
+ <class>CaptionsDialog</class>
5
+ <widget class="QDialog" name="CaptionsDialog">
6
+  <property name="geometry">
7
+   <rect>
8
+    <x>0</x>
9
+    <y>0</y>
10
+    <width>519</width>
11
+    <height>140</height>
12
+   </rect>
13
+  </property>
14
+  <property name="windowTitle">
15
+   <string>Captions</string>
16
+  </property>
17
+  <layout class="QVBoxLayout" name="verticalLayout">
18
+   <item>
19
+    <layout class="QFormLayout" name="formLayout">
20
+     <property name="labelAlignment">
21
+      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
22
+     </property>
23
+     <item row="1" column="0">
24
+      <widget class="QLabel" name="label">
25
+       <property name="text">
26
+        <string>Captions.AudioSource</string>
27
+       </property>
28
+       <property name="buddy">
29
+        <cstring>source</cstring>
30
+       </property>
31
+      </widget>
32
+     </item>
33
+     <item row="1" column="1">
34
+      <widget class="QComboBox" name="source">
35
+       <property name="insertPolicy">
36
+        <enum>QComboBox::InsertAlphabetically</enum>
37
+       </property>
38
+      </widget>
39
+     </item>
40
+     <item row="0" column="1">
41
+      <widget class="QCheckBox" name="enable">
42
+       <property name="text">
43
+        <string>Enable</string>
44
+       </property>
45
+      </widget>
46
+     </item>
47
+     <item row="2" column="0">
48
+      <widget class="QLabel" name="label_2">
49
+       <property name="text">
50
+        <string>Basic.Settings.General.Language</string>
51
+       </property>
52
+       <property name="buddy">
53
+        <cstring>language</cstring>
54
+       </property>
55
+      </widget>
56
+     </item>
57
+     <item row="2" column="1">
58
+      <widget class="QComboBox" name="language"/>
59
+     </item>
60
+    </layout>
61
+   </item>
62
+   <item>
63
+    <spacer name="verticalSpacer">
64
+     <property name="orientation">
65
+      <enum>Qt::Vertical</enum>
66
+     </property>
67
+     <property name="sizeHint" stdset="0">
68
+      <size>
69
+       <width>0</width>
70
+       <height>0</height>
71
+      </size>
72
+     </property>
73
+    </spacer>
74
+   </item>
75
+   <item>
76
+    <layout class="QHBoxLayout" name="horizontalLayout">
77
+     <item>
78
+      <spacer name="horizontalSpacer">
79
+       <property name="orientation">
80
+        <enum>Qt::Horizontal</enum>
81
+       </property>
82
+       <property name="sizeHint" stdset="0">
83
+        <size>
84
+         <width>40</width>
85
+         <height>20</height>
86
+        </size>
87
+       </property>
88
+      </spacer>
89
+     </item>
90
+     <item>
91
+      <widget class="QPushButton" name="accept">
92
+       <property name="text">
93
+        <string>OK</string>
94
+       </property>
95
+      </widget>
96
+     </item>
97
+     <item>
98
+      <spacer name="horizontalSpacer_2">
99
+       <property name="orientation">
100
+        <enum>Qt::Horizontal</enum>
101
+       </property>
102
+       <property name="sizeHint" stdset="0">
103
+        <size>
104
+         <width>40</width>
105
+         <height>20</height>
106
+        </size>
107
+       </property>
108
+      </spacer>
109
+     </item>
110
+    </layout>
111
+   </item>
112
+  </layout>
113
+ </widget>
114
+ <resources/>
115
+ <connections>
116
+  <connection>
117
+   <sender>accept</sender>
118
+   <signal>clicked()</signal>
119
+   <receiver>CaptionsDialog</receiver>
120
+   <slot>accept()</slot>
121
+   <hints>
122
+    <hint type="sourcelabel">
123
+     <x>268</x>
124
+     <y>331</y>
125
+    </hint>
126
+    <hint type="destinationlabel">
127
+     <x>229</x>
128
+     <y>-11</y>
129
+    </hint>
130
+   </hints>
131
+  </connection>
132
+ </connections>
133
+</ui>
134
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/forms/output-timer.ui -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/forms/output-timer.ui Changed
130
 
1
@@ -7,7 +7,7 @@
2
         <x>0</x>
3
         <y>0</y>
4
         <width>600</width>
5
-        <height>150</height>
6
+        <height>200</height>
7
       </rect>
8
     </property>
9
     <property name="windowTitle">
10
@@ -85,28 +85,28 @@
11
           </property>
12
         </widget>
13
       </item>
14
-      <item row="1" column="1">
15
+      <item row="2" column="1">
16
         <widget class="QLabel" name="streamStoppingIn">
17
           <property name="text">
18
             <string>OutputTimer.Stream.StoppingIn</string>
19
           </property>
20
         </widget>
21
       </item>
22
-      <item row="1" column="2">
23
+      <item row="2" column="2">
24
         <widget class="QLabel" name="streamTime">
25
           <property name="text">
26
             <string>00:00:00</string>
27
           </property>
28
         </widget>
29
       </item>
30
-      <item row="2" column="1">
31
+      <item row="3" column="1">
32
         <widget class="QLabel" name="recordingLabel">
33
           <property name="text">
34
             <string>OutputTimer.Record</string>
35
           </property>
36
         </widget>
37
       </item>
38
-      <item row="2" column="2">
39
+      <item row="3" column="2">
40
         <widget class="QSpinBox" name="recordingTimerHours">
41
           <property name="minimum">
42
             <number>0</number>
43
@@ -119,14 +119,14 @@
44
           </property>
45
         </widget>
46
       </item>
47
-      <item row="2" column="3">
48
+      <item row="3" column="3">
49
         <widget class="QLabel" name="hoursLabel_2">
50
           <property name="text">
51
             <string>Hours</string>
52
           </property>
53
         </widget>
54
       </item>
55
-      <item row="2" column="4">
56
+      <item row="3" column="4">
57
         <widget class="QSpinBox" name="recordingTimerMinutes">
58
           <property name="minimum">
59
             <number>0</number>
60
@@ -139,14 +139,14 @@
61
           </property>
62
         </widget>
63
       </item>
64
-      <item row="2" column="5">
65
+      <item row="3" column="5">
66
         <widget class="QLabel" name="minutesLabel_2">
67
           <property name="text">
68
             <string>Minutes</string>
69
           </property>
70
         </widget>
71
       </item>
72
-      <item row="2" column="6">
73
+      <item row="3" column="6">
74
         <widget class="QSpinBox" name="recordingTimerSeconds">
75
           <property name="minimum">
76
             <number>0</number>
77
@@ -159,34 +159,48 @@
78
           </property>
79
         </widget>
80
       </item>
81
-      <item row="2" column="7">
82
+      <item row="3" column="7">
83
         <widget class="QLabel" name="secondsLabel_2">
84
           <property name="text">
85
             <string>Seconds</string>
86
           </property>
87
         </widget>
88
       </item>
89
-      <item row="2" column="8">
90
+      <item row="3" column="8">
91
         <widget class="QPushButton" name="outputTimerRecord">
92
           <property name="text">
93
             <string>Start</string>
94
           </property>
95
         </widget>
96
       </item>
97
-      <item row="3" column="1">
98
+      <item row="5" column="1">
99
         <widget class="QLabel" name="recordStoppingIn">
100
           <property name="text">
101
             <string>OutputTimer.Record.StoppingIn</string>
102
           </property>
103
         </widget>
104
       </item>
105
-      <item row="3" column="2">
106
+      <item row="5" column="2">
107
         <widget class="QLabel" name="recordTime">
108
           <property name="text">
109
             <string>00:00:00</string>
110
           </property>
111
         </widget>
112
       </item>
113
+      <item row="1" column="1" colspan="3">
114
+        <widget class="QCheckBox" name="autoStartStreamTimer">
115
+          <property name="text">
116
+            <string>OutputTimer.Stream.EnableEverytime</string>
117
+          </property>
118
+        </widget>
119
+      </item>
120
+      <item row="4" column="1" colspan="3">
121
+        <widget class="QCheckBox" name="autoStartRecordTimer">
122
+          <property name="text">
123
+            <string>OutputTimer.Record.EnableEverytime</string>
124
+          </property>
125
+        </widget>
126
+      </item>
127
     </layout>
128
   </widget>
129
   <resources />
130
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/frontend-tools-config.h.in Added
5
 
1
@@ -0,0 +1,3 @@
2
+#pragma once
3
+
4
+#define BUILD_CAPTIONS @BUILD_CAPTIONS@
5
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/frontend-tools.c -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/frontend-tools.c Changed
39
 
1
@@ -1,4 +1,5 @@
2
 #include <obs-module.h>
3
+#include "frontend-tools-config.h"
4
 
5
 OBS_DECLARE_MODULE()
6
 OBS_MODULE_USE_DEFAULT_LOCALE("frontend-tools", "en-US")
7
@@ -7,6 +8,12 @@
8
 void InitSceneSwitcher();
9
 void FreeSceneSwitcher();
10
 #endif
11
+
12
+#if defined(_WIN32) && BUILD_CAPTIONS
13
+void InitCaptions();
14
+void FreeCaptions();
15
+#endif
16
+
17
 void InitOutputTimer();
18
 void FreeOutputTimer();
19
 
20
@@ -15,6 +22,9 @@
21
 #if defined(_WIN32) || defined(__APPLE__)
22
    InitSceneSwitcher();
23
 #endif
24
+#if defined(_WIN32) && BUILD_CAPTIONS
25
+   InitCaptions();
26
+#endif
27
    InitOutputTimer();
28
    return true;
29
 }
30
@@ -24,5 +34,8 @@
31
 #if defined(_WIN32) || defined(__APPLE__)
32
    FreeSceneSwitcher();
33
 #endif
34
+#if defined(_WIN32) && BUILD_CAPTIONS
35
+   FreeCaptions();
36
+#endif
37
    FreeOutputTimer();
38
 }
39
obs-studio-0.16.6.tar.xz/UI/frontend-plugins/frontend-tools/output-timer.cpp -> obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/output-timer.cpp Changed
78
 
1
@@ -61,7 +61,7 @@
2
 
3
 void OutputTimer::StreamTimerStart()
4
 {
5
-   if (!isVisible()) {
6
+   if (!isVisible() && ui->autoStartStreamTimer->isChecked() == false) {
7
        streamingAlreadyActive = true;
8
        return;
9
    }
10
@@ -88,14 +88,14 @@
11
 
12
    streamingTimer->start();
13
    streamingTimerDisplay->start(1000);
14
-   ui->outputTimerStream->setText(tr("Stop"));
15
+   ui->outputTimerStream->setText(obs_module_text("Stop"));
16
 
17
    UpdateStreamTimerDisplay();
18
 }
19
 
20
 void OutputTimer::RecordTimerStart()
21
 {
22
-   if (!isVisible()) {
23
+   if (!isVisible() && ui->autoStartRecordTimer->isChecked() == false) {
24
        recordingAlreadyActive = true;
25
        return;
26
    }
27
@@ -122,7 +122,7 @@
28
 
29
    recordingTimer->start();
30
    recordingTimerDisplay->start(1000);
31
-   ui->outputTimerRecord->setText(tr("Stop"));
32
+   ui->outputTimerRecord->setText(obs_module_text("Stop"));
33
 
34
    UpdateRecordTimerDisplay();
35
 }
36
@@ -137,7 +137,7 @@
37
    if (streamingTimer->isActive())
38
        streamingTimer->stop();
39
 
40
-   ui->outputTimerStream->setText(tr("Start"));
41
+   ui->outputTimerStream->setText(obs_module_text("Start"));
42
 
43
    if (streamingTimerDisplay->isActive())
44
        streamingTimerDisplay->stop();
45
@@ -155,7 +155,7 @@
46
    if (recordingTimer->isActive())
47
        recordingTimer->stop();
48
 
49
-   ui->outputTimerRecord->setText(tr("Start"));
50
+   ui->outputTimerRecord->setText(obs_module_text("Start"));
51
 
52
    if (recordingTimerDisplay->isActive())
53
        recordingTimerDisplay->stop();
54
@@ -229,6 +229,11 @@
55
        obs_data_set_int(obj, "recordTimerSeconds",
56
                ot->ui->recordingTimerSeconds->value());
57
 
58
+       obs_data_set_bool(obj, "autoStartStreamTimer",
59
+               ot->ui->autoStartStreamTimer->isChecked());
60
+       obs_data_set_bool(obj, "autoStartRecordTimer",
61
+               ot->ui->autoStartRecordTimer->isChecked());
62
+
63
        obs_data_set_obj(save_data, "output-timer", obj);
64
 
65
        obs_data_release(obj);
66
@@ -253,6 +258,11 @@
67
        ot->ui->recordingTimerSeconds->setValue(
68
                obs_data_get_int(obj, "recordTimerSeconds"));
69
 
70
+       ot->ui->autoStartStreamTimer->setChecked(
71
+               obs_data_get_bool(obj, "autoStartStreamTimer"));
72
+       ot->ui->autoStartRecordTimer->setChecked(
73
+               obs_data_get_bool(obj, "autoStartRecordTimer"));
74
+
75
        obs_data_release(obj);
76
    }
77
 }
78
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/tool-helpers.hpp Added
38
 
1
@@ -0,0 +1,36 @@
2
+#pragma once
3
+
4
+#include <obs.hpp>
5
+#include <string>
6
+#include <QString>
7
+
8
+static inline OBSWeakSource GetWeakSourceByName(const char *name)
9
+{
10
+   OBSWeakSource weak;
11
+   obs_source_t *source = obs_get_source_by_name(name);
12
+   if (source) {
13
+       weak = obs_source_get_weak_source(source);
14
+       obs_weak_source_release(weak);
15
+       obs_source_release(source);
16
+   }
17
+
18
+   return weak;
19
+}
20
+
21
+static inline OBSWeakSource GetWeakSourceByQString(const QString &name)
22
+{
23
+   return GetWeakSourceByName(name.toUtf8().constData());
24
+}
25
+
26
+static inline std::string GetWeakSourceName(obs_weak_source_t *weak_source)
27
+{
28
+   std::string name;
29
+
30
+   obs_source_t *source = obs_weak_source_get_source(weak_source);
31
+   if (source) {
32
+       name = obs_source_get_name(source);
33
+       obs_source_release(source);
34
+   }
35
+
36
+   return name;
37
+}
38
obs-studio-0.16.6.tar.xz/UI/installer/mp-installer.nsi -> obs-studio-0.17.0.tar.xz/UI/installer/mp-installer.nsi Changed
23
 
1
@@ -224,7 +224,11 @@
2
    ${endif}
3
 
4
    SetOutPath "$INSTDIR\bin\32bit"
5
-   CreateShortCut "$DESKTOP\OBS Studio.lnk" "$INSTDIR\bin\32bit\obs32.exe"
6
+   ${if} ${RunningX64}
7
+       CreateShortCut "$DESKTOP\OBS Studio.lnk" "$INSTDIR\bin\64bit\obs64.exe"
8
+   ${else}
9
+       CreateShortCut "$DESKTOP\OBS Studio.lnk" "$INSTDIR\bin\32bit\obs32.exe"
10
+   ${endif}
11
    CreateDirectory "$SMPROGRAMS\OBS Studio"
12
    CreateShortCut "$SMPROGRAMS\OBS Studio\OBS Studio (32bit).lnk" "$INSTDIR\bin\32bit\obs32.exe"
13
    CreateShortCut "$SMPROGRAMS\OBS Studio\Uninstall.lnk" "$INSTDIR\uninstall.exe"
14
@@ -288,7 +292,7 @@
15
 
16
            File "intel_rs_sdk_runtime_websetup_10.0.26.0396.exe"
17
            ExecWait '"$PLUGINSDIR\realsense\intel_rs_sdk_runtime_websetup_10.0.26.0396.exe" --finstall=personify --fnone=all'
18
-       {endif}
19
+       ${endif}
20
 
21
        SetOutPath "$INSTDIR\bin\32bit"
22
    SectionEnd
23
obs-studio-0.16.6.tar.xz/UI/obs-app.cpp -> obs-studio-0.17.0.tar.xz/UI/obs-app.cpp Changed
96
 
1
@@ -67,6 +67,11 @@
2
 string opt_starting_profile;
3
 string opt_starting_scene;
4
 
5
+// AMD PowerXpress High Performance Flags
6
+#ifdef _MSC_VER
7
+extern "C" __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
8
+#endif
9
+
10
 QObject *CreateShortcutFilter()
11
 {
12
    return new OBSEventFilter([](QObject *obj, QEvent *event)
13
@@ -1110,79 +1115,9 @@
14
 string GenerateSpecifiedFilename(const char *extension, bool noSpace,
15
        const char *format)
16
 {
17
-   time_t now = time(0);
18
-   struct tm *cur_time;
19
-   cur_time = localtime(&now);
20
-
21
-   const size_t spec_count = 23;
22
-   const char *spec[][2] = {
23
-       {"%CCYY", "%Y"},
24
-       {"%YY",   "%y"},
25
-       {"%MM",   "%m"},
26
-       {"%DD",   "%d"},
27
-       {"%hh",   "%H"},
28
-       {"%mm",   "%M"},
29
-       {"%ss",   "%S"},
30
-       {"%%",    "%%"},
31
-
32
-       {"%a",    ""},
33
-       {"%A",    ""},
34
-       {"%b",    ""},
35
-       {"%B",    ""},
36
-       {"%d",    ""},
37
-       {"%H",    ""},
38
-       {"%I",    ""},
39
-       {"%m",    ""},
40
-       {"%M",    ""},
41
-       {"%p",    ""},
42
-       {"%S",    ""},
43
-       {"%y",    ""},
44
-       {"%Y",    ""},
45
-       {"%z",    ""},
46
-       {"%Z",    ""},
47
-   };
48
-
49
-   char convert[128] = {};
50
-   string sf = format;
51
-   string c;
52
-   size_t pos = 0, len;
53
-
54
-   while (pos < sf.length()) {
55
-       len = 0;
56
-       for (size_t i = 0; i < spec_count && len == 0; i++) {
57
-
58
-           if (sf.find(spec[i][0], pos) == pos) {
59
-               if (strlen(spec[i][1]))
60
-                   strftime(convert, sizeof(convert),
61
-                           spec[i][1], cur_time);
62
-               else
63
-                   strftime(convert, sizeof(convert),
64
-                           spec[i][0], cur_time);
65
-
66
-               len = strlen(spec[i][0]);
67
-
68
-               c = convert;
69
-               if (c.length() && c.find_first_not_of(' ') !=
70
-                       std::string::npos)
71
-                   sf.replace(pos, len, convert);
72
-           }
73
-       }
74
-
75
-       if (len)
76
-           pos += strlen(convert);
77
-       else if (!len && sf.at(pos) == '%')
78
-           sf.erase(pos,1);
79
-       else
80
-           pos++;
81
-   }
82
-
83
-   if (noSpace)
84
-       replace(sf.begin(), sf.end(), ' ', '_');
85
-
86
-   sf += '.';
87
-   sf += extension;
88
-
89
-   return (sf.length() < 256) ? sf : sf.substr(0, 255);
90
+   BPtr<char> filename = os_generate_formatted_filename(extension,
91
+           !noSpace, format);
92
+   return string(filename);
93
 }
94
 
95
 vector<pair<string, string>> GetLocaleNames()
96
obs-studio-0.16.6.tar.xz/UI/obs-frontend-api/obs-frontend-api.cpp -> obs-studio-0.17.0.tar.xz/UI/obs-frontend-api/obs-frontend-api.cpp Changed
39
 
1
@@ -205,6 +205,23 @@
2
        : false;
3
 }
4
 
5
+void obs_frontend_replay_buffer_start(void)
6
+{
7
+   if (callbacks_valid()) c->obs_frontend_replay_buffer_start();
8
+}
9
+
10
+void obs_frontend_replay_buffer_stop(void)
11
+{
12
+   if (callbacks_valid()) c->obs_frontend_replay_buffer_stop();
13
+}
14
+
15
+bool obs_frontend_replay_buffer_active(void)
16
+{
17
+   return !!callbacks_valid()
18
+       ? c->obs_frontend_replay_buffer_active()
19
+       : false;
20
+}
21
+
22
 void *obs_frontend_add_tools_menu_qaction(const char *name)
23
 {
24
    return !!callbacks_valid()
25
@@ -248,6 +265,13 @@
26
        : nullptr;
27
 }
28
 
29
+obs_output_t *obs_frontend_get_replay_buffer_output(void)
30
+{
31
+   return !!callbacks_valid()
32
+       ? c->obs_frontend_get_replay_buffer_output()
33
+       : nullptr;
34
+}
35
+
36
 config_t *obs_frontend_get_profile_config(void)
37
 {
38
    return !!callbacks_valid()
39
obs-studio-0.16.6.tar.xz/UI/obs-frontend-api/obs-frontend-api.h -> obs-studio-0.17.0.tar.xz/UI/obs-frontend-api/obs-frontend-api.h Changed
34
 
1
@@ -70,6 +70,10 @@
2
 EXPORT void obs_frontend_recording_stop(void);
3
 EXPORT bool obs_frontend_recording_active(void);
4
 
5
+EXPORT void obs_frontend_replay_buffer_start(void);
6
+EXPORT void obs_frontend_replay_buffer_stop(void);
7
+EXPORT bool obs_frontend_replay_buffer_active(void);
8
+
9
 typedef void (*obs_frontend_cb)(void *private_data);
10
 
11
 EXPORT void *obs_frontend_add_tools_menu_qaction(const char *name);
12
@@ -94,7 +98,12 @@
13
    OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED,
14
    OBS_FRONTEND_EVENT_PROFILE_CHANGED,
15
    OBS_FRONTEND_EVENT_PROFILE_LIST_CHANGED,
16
-   OBS_FRONTEND_EVENT_EXIT
17
+   OBS_FRONTEND_EVENT_EXIT,
18
+
19
+   OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTING,
20
+   OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED,
21
+   OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPING,
22
+   OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED
23
 };
24
 
25
 typedef void (*obs_frontend_event_cb)(enum obs_frontend_event event,
26
@@ -116,6 +125,7 @@
27
 
28
 EXPORT obs_output_t *obs_frontend_get_streaming_output(void);
29
 EXPORT obs_output_t *obs_frontend_get_recording_output(void);
30
+EXPORT obs_output_t *obs_frontend_get_replay_buffer_output(void);
31
 
32
 EXPORT config_t *obs_frontend_get_profile_config(void);
33
 EXPORT config_t *obs_frontend_get_global_config(void);
34
obs-studio-0.16.6.tar.xz/UI/obs-frontend-api/obs-frontend-internal.hpp -> obs-studio-0.17.0.tar.xz/UI/obs-frontend-api/obs-frontend-internal.hpp Changed
20
 
1
@@ -39,6 +39,10 @@
2
    virtual void obs_frontend_recording_stop(void)=0;
3
    virtual bool obs_frontend_recording_active(void)=0;
4
 
5
+   virtual void obs_frontend_replay_buffer_start(void)=0;
6
+   virtual void obs_frontend_replay_buffer_stop(void)=0;
7
+   virtual bool obs_frontend_replay_buffer_active(void)=0;
8
+
9
    virtual void *obs_frontend_add_tools_menu_qaction(const char *name)=0;
10
    virtual void obs_frontend_add_tools_menu_item(const char *name,
11
            obs_frontend_cb callback, void *private_data)=0;
12
@@ -50,6 +54,7 @@
13
 
14
    virtual obs_output_t *obs_frontend_get_streaming_output(void)=0;
15
    virtual obs_output_t *obs_frontend_get_recording_output(void)=0;
16
+   virtual obs_output_t *obs_frontend_get_replay_buffer_output(void)=0;
17
 
18
    virtual config_t *obs_frontend_get_profile_config(void)=0;
19
    virtual config_t *obs_frontend_get_global_config(void)=0;
20
obs-studio-0.16.6.tar.xz/UI/window-basic-filters.cpp -> obs-studio-0.17.0.tar.xz/UI/window-basic-filters.cpp Changed
9
 
1
@@ -147,6 +147,7 @@
2
 void OBSBasicFilters::UpdatePropertiesView(int row, bool async)
3
 {
4
    if (view) {
5
+       ui->rightLayout->removeWidget(view);
6
        view->deleteLater();
7
        view = nullptr;
8
    }
9
obs-studio-0.16.6.tar.xz/UI/window-basic-main-outputs.cpp -> obs-studio-0.17.0.tar.xz/UI/window-basic-main-outputs.cpp Changed
375
 
1
@@ -84,6 +84,36 @@
2
    UNUSED_PARAMETER(params);
3
 }
4
 
5
+static void OBSStartReplayBuffer(void *data, calldata_t *params)
6
+{
7
+   BasicOutputHandler *output = static_cast<BasicOutputHandler*>(data);
8
+
9
+   output->replayBufferActive = true;
10
+   QMetaObject::invokeMethod(output->main, "ReplayBufferStart");
11
+
12
+   UNUSED_PARAMETER(params);
13
+}
14
+
15
+static void OBSStopReplayBuffer(void *data, calldata_t *params)
16
+{
17
+   BasicOutputHandler *output = static_cast<BasicOutputHandler*>(data);
18
+   int code = (int)calldata_int(params, "code");
19
+
20
+   output->replayBufferActive = false;
21
+   QMetaObject::invokeMethod(output->main,
22
+           "ReplayBufferStop", Q_ARG(int, code));
23
+
24
+   UNUSED_PARAMETER(params);
25
+}
26
+
27
+static void OBSReplayBufferStopping(void *data, calldata_t *params)
28
+{
29
+   BasicOutputHandler *output = static_cast<BasicOutputHandler*>(data);
30
+   QMetaObject::invokeMethod(output->main, "ReplayBufferStopping");
31
+
32
+   UNUSED_PARAMETER(params);
33
+}
34
+
35
 static void FindBestFilename(string &strPath, bool noSpace)
36
 {
37
    int num = 2;
38
@@ -154,6 +184,7 @@
39
    string                 videoEncoder;
40
    string                 videoQuality;
41
    bool                   usingRecordingPreset = false;
42
+   bool                   recordingConfigured = false;
43
    bool                   ffmpegOutput = false;
44
    bool                   lowCPUx264 = false;
45
 
46
@@ -179,12 +210,18 @@
47
 
48
    void LoadStreamingPreset_h264(const char *encoder);
49
 
50
+   void UpdateRecording();
51
+   bool ConfigureRecording(bool useReplayBuffer);
52
+
53
    virtual bool StartStreaming(obs_service_t *service) override;
54
    virtual bool StartRecording() override;
55
+   virtual bool StartReplayBuffer() override;
56
    virtual void StopStreaming(bool force) override;
57
    virtual void StopRecording(bool force) override;
58
+   virtual void StopReplayBuffer(bool force) override;
59
    virtual bool StreamingActive() const override;
60
    virtual bool RecordingActive() const override;
61
+   virtual bool ReplayBufferActive() const override;
62
 };
63
 
64
 void SimpleOutput::LoadRecordingPreset_Lossless()
65
@@ -306,6 +343,32 @@
66
    LoadRecordingPreset();
67
 
68
    if (!ffmpegOutput) {
69
+       bool useReplayBuffer = config_get_bool(main->Config(),
70
+               "SimpleOutput", "RecRB");
71
+       if (useReplayBuffer) {
72
+           const char *str = config_get_string(main->Config(),
73
+                   "Hotkeys", "ReplayBuffer");
74
+           obs_data_t *hotkey = obs_data_create_from_json(str);
75
+           replayBuffer = obs_output_create("replay_buffer",
76
+                   Str("ReplayBuffer"), nullptr, hotkey);
77
+
78
+           obs_data_release(hotkey);
79
+           if (!replayBuffer)
80
+               throw "Failed to create replay buffer output "
81
+                     "(simple output)";
82
+           obs_output_release(replayBuffer);
83
+
84
+           signal_handler_t *signal =
85
+               obs_output_get_signal_handler(replayBuffer);
86
+
87
+           startReplayBuffer.Connect(signal, "start",
88
+                   OBSStartReplayBuffer, this);
89
+           stopReplayBuffer.Connect(signal, "stop",
90
+                   OBSStopReplayBuffer, this);
91
+           replayBufferStopping.Connect(signal, "stopping",
92
+                   OBSReplayBufferStopping, this);
93
+       }
94
+
95
        fileOutput = obs_output_create("ffmpeg_muxer",
96
                "simple_file_output", nullptr, nullptr);
97
        if (!fileOutput)
98
@@ -624,6 +687,19 @@
99
    return false;
100
 }
101
 
102
+static void remove_reserved_file_characters(string &s)
103
+{
104
+   replace(s.begin(), s.end(), '/', '_');
105
+   replace(s.begin(), s.end(), '\\', '_');
106
+   replace(s.begin(), s.end(), '*', '_');
107
+   replace(s.begin(), s.end(), '?', '_');
108
+   replace(s.begin(), s.end(), '"', '_');
109
+   replace(s.begin(), s.end(), '|', '_');
110
+   replace(s.begin(), s.end(), ':', '_');
111
+   replace(s.begin(), s.end(), '>', '_');
112
+   replace(s.begin(), s.end(), '<', '_');
113
+}
114
+
115
 static void ensure_directory_exists(string &path)
116
 {
117
    replace(path.begin(), path.end(), '\\', '/');
118
@@ -636,8 +712,11 @@
119
    os_mkdirs(directory.c_str());
120
 }
121
 
122
-bool SimpleOutput::StartRecording()
123
+void SimpleOutput::UpdateRecording()
124
 {
125
+   if (replayBufferActive || recordingActive)
126
+       return;
127
+
128
    if (usingRecordingPreset) {
129
        if (!ffmpegOutput)
130
            UpdateRecordingSettings();
131
@@ -648,6 +727,20 @@
132
    if (!Active())
133
        SetupOutputs();
134
 
135
+   if (!ffmpegOutput) {
136
+       obs_output_set_video_encoder(fileOutput, h264Recording);
137
+       obs_output_set_audio_encoder(fileOutput, aacRecording, 0);
138
+   }
139
+   if (replayBuffer) {
140
+       obs_output_set_video_encoder(replayBuffer, h264Recording);
141
+       obs_output_set_audio_encoder(replayBuffer, aacRecording, 0);
142
+   }
143
+
144
+   recordingConfigured = true;
145
+}
146
+
147
+bool SimpleOutput::ConfigureRecording(bool updateReplayBuffer)
148
+{
149
    const char *path = config_get_string(main->Config(),
150
            "SimpleOutput", "FilePath");
151
    const char *format = config_get_string(main->Config(),
152
@@ -660,6 +753,14 @@
153
                "FilenameFormatting");
154
    bool overwriteIfExists = config_get_bool(main->Config(), "Output",
155
                "OverwriteIfExists");
156
+   const char *rbPrefix = config_get_string(main->Config(), "SimpleOutput",
157
+               "RecRBPrefix");
158
+   const char *rbSuffix = config_get_string(main->Config(), "SimpleOutput",
159
+               "RecRBSuffix");
160
+   int rbTime = config_get_int(main->Config(), "SimpleOutput",
161
+           "RecRBTime");
162
+   int rbSize = config_get_int(main->Config(), "SimpleOutput",
163
+           "RecRBSize");
164
 
165
    os_dir_t *dir = path ? os_opendir(path) : nullptr;
166
 
167
@@ -689,25 +790,66 @@
168
    if (!overwriteIfExists)
169
        FindBestFilename(strPath, noSpace);
170
 
171
-   if (!ffmpegOutput) {
172
-       obs_output_set_video_encoder(fileOutput, h264Recording);
173
-       obs_output_set_audio_encoder(fileOutput, aacRecording, 0);
174
+   obs_data_t *settings = obs_data_create();
175
+   if (updateReplayBuffer) {
176
+       string f;
177
+
178
+       if (rbPrefix && *rbPrefix) {
179
+           f += rbPrefix;
180
+           if (f.back() != ' ')
181
+               f += " ";
182
+       }
183
+
184
+       f += filenameFormat;
185
+
186
+       if (rbSuffix && *rbSuffix) {
187
+           if (*rbSuffix != ' ')
188
+               f += " ";
189
+           f += rbSuffix;
190
+       }
191
+
192
+       remove_reserved_file_characters(f);
193
+
194
+       obs_data_set_string(settings, "directory", path);
195
+       obs_data_set_string(settings, "format", f.c_str());
196
+       obs_data_set_string(settings, "extension", format);
197
+       obs_data_set_int(settings, "max_time_sec", rbTime);
198
+       obs_data_set_int(settings, "max_size_mb",
199
+               usingRecordingPreset ? rbSize : 0);
200
+   } else {
201
+       obs_data_set_string(settings, ffmpegOutput ? "url" : "path",
202
+               strPath.c_str());
203
    }
204
 
205
-   obs_data_t *settings = obs_data_create();
206
-   obs_data_set_string(settings, ffmpegOutput ? "url" : "path",
207
-           strPath.c_str());
208
    obs_data_set_string(settings, "muxer_settings", mux);
209
 
210
-   obs_output_update(fileOutput, settings);
211
+   if (updateReplayBuffer)
212
+       obs_output_update(replayBuffer, settings);
213
+   else
214
+       obs_output_update(fileOutput, settings);
215
 
216
    obs_data_release(settings);
217
+   return true;
218
+}
219
 
220
-   if (obs_output_start(fileOutput)) {
221
-       return true;
222
-   }
223
+bool SimpleOutput::StartRecording()
224
+{
225
+   UpdateRecording();
226
+   if (!ConfigureRecording(false))
227
+       return false;
228
+   if (!obs_output_start(fileOutput))
229
+       return false;
230
+   return true;
231
+}
232
 
233
-   return false;
234
+bool SimpleOutput::StartReplayBuffer()
235
+{
236
+   UpdateRecording();
237
+   if (!ConfigureRecording(true))
238
+       return false;
239
+   if (!obs_output_start(replayBuffer))
240
+       return false;
241
+   return true;
242
 }
243
 
244
 void SimpleOutput::StopStreaming(bool force)
245
@@ -726,6 +868,14 @@
246
        obs_output_stop(fileOutput);
247
 }
248
 
249
+void SimpleOutput::StopReplayBuffer(bool force)
250
+{
251
+   if (force)
252
+       obs_output_force_stop(replayBuffer);
253
+   else
254
+       obs_output_stop(replayBuffer);
255
+}
256
+
257
 bool SimpleOutput::StreamingActive() const
258
 {
259
    return obs_output_active(streamOutput);
260
@@ -736,10 +886,15 @@
261
    return obs_output_active(fileOutput);
262
 }
263
 
264
+bool SimpleOutput::ReplayBufferActive() const
265
+{
266
+   return obs_output_active(replayBuffer);
267
+}
268
+
269
 /* ------------------------------------------------------------------------ */
270
 
271
 struct AdvancedOutput : BasicOutputHandler {
272
-   OBSEncoder             aacTrack[4];
273
+   OBSEncoder             aacTrack[MAX_AUDIO_MIXES];
274
    OBSEncoder             h264Streaming;
275
    OBSEncoder             h264Recording;
276
 
277
@@ -747,7 +902,7 @@
278
    bool                   ffmpegRecording;
279
    bool                   useStreamEncoder;
280
 
281
-   string                 aacEncoderID[4];
282
+   string                 aacEncoderID[MAX_AUDIO_MIXES];
283
 
284
    AdvancedOutput(OBSBasic *main_);
285
 
286
@@ -844,7 +999,7 @@
287
              "(advanced output)";
288
    obs_encoder_release(h264Streaming);
289
 
290
-   for (int i = 0; i < 4; i++) {
291
+   for (int i = 0; i < MAX_AUDIO_MIXES; i++) {
292
        char name[9];
293
        sprintf(name, "adv_aac%d", i);
294
 
295
@@ -939,7 +1094,7 @@
296
        for (; i < trackCount; i++)
297
            obs_output_set_audio_encoder(streamOutput, aacTrack[i],
298
                    i);
299
-       for (; i < 4; i++)
300
+       for (; i < MAX_AUDIO_MIXES; i++)
301
            obs_output_set_audio_encoder(streamOutput, nullptr, i);
302
 
303
    } else {
304
@@ -1064,31 +1219,30 @@
305
 
306
 inline void AdvancedOutput::UpdateAudioSettings()
307
 {
308
-   const char *name1 = config_get_string(main->Config(), "AdvOut",
309
-           "Track1Name");
310
-   const char *name2 = config_get_string(main->Config(), "AdvOut",
311
-           "Track2Name");
312
-   const char *name3 = config_get_string(main->Config(), "AdvOut",
313
-           "Track3Name");
314
-   const char *name4 = config_get_string(main->Config(), "AdvOut",
315
-           "Track4Name");
316
    bool applyServiceSettings = config_get_bool(main->Config(), "AdvOut",
317
            "ApplyServiceSettings");
318
    int streamTrackIndex = config_get_int(main->Config(), "AdvOut",
319
            "TrackIndex");
320
-   obs_data_t *settings[4];
321
+   obs_data_t *settings[MAX_AUDIO_MIXES];
322
 
323
-   for (size_t i = 0; i < 4; i++) {
324
+   for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
325
        settings[i] = obs_data_create();
326
        obs_data_set_int(settings[i], "bitrate", GetAudioBitrate(i));
327
    }
328
 
329
-   SetEncoderName(aacTrack[0], name1, "Track1");
330
-   SetEncoderName(aacTrack[1], name2, "Track2");
331
-   SetEncoderName(aacTrack[2], name3, "Track3");
332
-   SetEncoderName(aacTrack[3], name4, "Track4");
333
+   for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
334
+       string cfg_name = "Track";
335
+       cfg_name += to_string((int)i + 1);
336
+       cfg_name += "Name";
337
+       const char *name = config_get_string(main->Config(), "AdvOut",
338
+               cfg_name.c_str());
339
+
340
+       string def_name = "Track";
341
+       def_name += to_string((int)i + 1);
342
+       SetEncoderName(aacTrack[i], name, def_name.c_str());
343
+   }
344
 
345
-   for (size_t i = 0; i < 4; i++) {
346
+   for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
347
        if (applyServiceSettings && (int)(i + 1) == streamTrackIndex)
348
            obs_service_apply_encoder_settings(main->GetService(),
349
                    nullptr, settings[i]);
350
@@ -1103,10 +1257,8 @@
351
    obs_encoder_set_video(h264Streaming, obs_get_video());
352
    if (h264Recording)
353
        obs_encoder_set_video(h264Recording, obs_get_video());
354
-   obs_encoder_set_audio(aacTrack[0], obs_get_audio());
355
-   obs_encoder_set_audio(aacTrack[1], obs_get_audio());
356
-   obs_encoder_set_audio(aacTrack[2], obs_get_audio());
357
-   obs_encoder_set_audio(aacTrack[3], obs_get_audio());
358
+   for (size_t i = 0; i < MAX_AUDIO_MIXES; i++)
359
+       obs_encoder_set_audio(aacTrack[i], obs_get_audio());
360
 
361
    SetupStreaming();
362
 
363
@@ -1118,9 +1270,10 @@
364
 
365
 int AdvancedOutput::GetAudioBitrate(size_t i) const
366
 {
367
-   const char *names[] = {
368
+   static const char *names[] = {
369
        "Track1Bitrate", "Track2Bitrate",
370
        "Track3Bitrate", "Track4Bitrate",
371
+       "Track5Bitrate", "Track6Bitrate",
372
    };
373
    int bitrate = (int)config_get_uint(main->Config(), "AdvOut", names[i]);
374
    return FindClosestAvailableAACBitrate(bitrate);
375
obs-studio-0.16.6.tar.xz/UI/window-basic-main-outputs.hpp -> obs-studio-0.17.0.tar.xz/UI/window-basic-main-outputs.hpp Changed
47
 
1
@@ -5,18 +5,23 @@
2
 struct BasicOutputHandler {
3
    OBSOutput              fileOutput;
4
    OBSOutput              streamOutput;
5
+   OBSOutput              replayBuffer;
6
    bool                   streamingActive = false;
7
    bool                   recordingActive = false;
8
    bool                   delayActive = false;
9
+   bool                   replayBufferActive = false;
10
    OBSBasic               *main;
11
 
12
    OBSSignal              startRecording;
13
    OBSSignal              stopRecording;
14
+   OBSSignal              startReplayBuffer;
15
+   OBSSignal              stopReplayBuffer;
16
    OBSSignal              startStreaming;
17
    OBSSignal              stopStreaming;
18
    OBSSignal              streamDelayStarting;
19
    OBSSignal              streamStopping;
20
    OBSSignal              recordStopping;
21
+   OBSSignal              replayBufferStopping;
22
 
23
    inline BasicOutputHandler(OBSBasic *main_) : main(main_) {}
24
 
25
@@ -24,16 +29,20 @@
26
 
27
    virtual bool StartStreaming(obs_service_t *service) = 0;
28
    virtual bool StartRecording() = 0;
29
+   virtual bool StartReplayBuffer() {return false;}
30
    virtual void StopStreaming(bool force = false) = 0;
31
    virtual void StopRecording(bool force = false) = 0;
32
+   virtual void StopReplayBuffer(bool force = false) {(void)force;}
33
    virtual bool StreamingActive() const = 0;
34
    virtual bool RecordingActive() const = 0;
35
+   virtual bool ReplayBufferActive() const {return false;}
36
 
37
    virtual void Update() = 0;
38
 
39
    inline bool Active() const
40
    {
41
-       return streamingActive || recordingActive || delayActive;
42
+       return streamingActive || recordingActive || delayActive ||
43
+           replayBufferActive;
44
    }
45
 };
46
 
47
obs-studio-0.16.6.tar.xz/UI/window-basic-main-profiles.cpp -> obs-studio-0.17.0.tar.xz/UI/window-basic-main-profiles.cpp Changed
95
 
1
@@ -20,6 +20,7 @@
2
 #include <util/util.hpp>
3
 #include <QMessageBox>
4
 #include <QVariant>
5
+#include <QFileDialog>
6
 #include "window-basic-main.hpp"
7
 #include "window-namedialog.hpp"
8
 #include "qt-wrappers.hpp"
9
@@ -448,6 +449,85 @@
10
    }
11
 }
12
 
13
+void OBSBasic::on_actionImportProfile_triggered()
14
+{
15
+   char path[512];
16
+
17
+   QString home = QDir::homePath();
18
+
19
+   int ret = GetConfigPath(path, 512, "obs-studio/basic/profiles/");
20
+   if (ret <= 0) {
21
+       blog(LOG_WARNING, "Failed to get profile config path");
22
+       return;
23
+   }
24
+
25
+   QString dir = QFileDialog::getExistingDirectory(
26
+           this,
27
+           QTStr("Basic.MainMenu.Profile.Import"),
28
+           home,
29
+           QFileDialog::ShowDirsOnly |
30
+           QFileDialog::DontResolveSymlinks);
31
+
32
+   if (!dir.isEmpty() && !dir.isNull()) {
33
+       QString inputPath = QString::fromUtf8(path);
34
+       QFileInfo finfo(dir);
35
+       QString directory = finfo.fileName();
36
+       QString profileDir = inputPath + directory;
37
+       QDir folder(profileDir);
38
+
39
+       if (!folder.exists()) {
40
+           folder.mkpath(profileDir);
41
+           QFile::copy(dir + "/basic.ini",
42
+                   profileDir + "/basic.ini");
43
+           QFile::copy(dir + "/service.json",
44
+                   profileDir + "/service.json");
45
+           RefreshProfiles();
46
+       } else {
47
+           QMessageBox::information(this,
48
+                   QTStr("Basic.MainMenu.Profile.Import"),
49
+                   QTStr("Basic.MainMenu.Profile.Exists"));
50
+       }
51
+   }
52
+}
53
+
54
+void OBSBasic::on_actionExportProfile_triggered()
55
+{
56
+   char path[512];
57
+
58
+   QString home = QDir::homePath();
59
+
60
+   QString currentProfile =
61
+       QString::fromUtf8(config_get_string(App()->GlobalConfig(),
62
+       "Basic", "ProfileDir"));
63
+
64
+   int ret = GetConfigPath(path, 512, "obs-studio/basic/profiles/");
65
+   if (ret <= 0) {
66
+       blog(LOG_WARNING, "Failed to get profile config path");
67
+       return;
68
+   }
69
+
70
+   QString dir = QFileDialog::getExistingDirectory(
71
+           this,
72
+           QTStr("Basic.MainMenu.Profile.Export"),
73
+           home,
74
+           QFileDialog::ShowDirsOnly |
75
+           QFileDialog::DontResolveSymlinks);
76
+
77
+   if (!dir.isEmpty() && !dir.isNull()) {
78
+       QString outputDir = dir + "/" + currentProfile;
79
+       QString inputPath = QString::fromUtf8(path);
80
+       QDir folder(outputDir);
81
+
82
+       if (!folder.exists()) {
83
+           folder.mkpath(outputDir);
84
+           QFile::copy(inputPath + currentProfile + "/basic.ini",
85
+                   outputDir + "/basic.ini");
86
+           QFile::copy(inputPath + currentProfile + "/service.json",
87
+                   outputDir + "/service.json");
88
+       }
89
+   }
90
+}
91
+
92
 void OBSBasic::ChangeProfile()
93
 {
94
    QAction *action = reinterpret_cast<QAction*>(sender());
95
obs-studio-0.16.6.tar.xz/UI/window-basic-main-scene-collections.cpp -> obs-studio-0.17.0.tar.xz/UI/window-basic-main-scene-collections.cpp Changed
105
 
1
@@ -19,6 +19,8 @@
2
 #include <util/util.hpp>
3
 #include <QMessageBox>
4
 #include <QVariant>
5
+#include <QFileDialog>
6
+#include <QStandardPaths>
7
 #include "item-widget-helpers.hpp"
8
 #include "window-basic-main.hpp"
9
 #include "window-namedialog.hpp"
10
@@ -191,7 +193,7 @@
11
    int count = 0;
12
 
13
    for (int i = 0; i < menuActions.count(); i++) {
14
-       QVariant v = menuActions[i]->property("fileName");
15
+       QVariant v = menuActions[i]->property("file_name");
16
        if (v.typeName() != nullptr)
17
            delete menuActions[i];
18
    }
19
@@ -205,7 +207,7 @@
20
        file.erase(file.size() - 5, 5);
21
 
22
        QAction *action = new QAction(QT_UTF8(name), this);
23
-       action->setProperty("fileName", QT_UTF8(path));
24
+       action->setProperty("file_name", QT_UTF8(path));
25
        connect(action, &QAction::triggered,
26
                this, &OBSBasic::ChangeSceneCollection);
27
        action->setCheckable(true);
28
@@ -347,6 +349,67 @@
29
    }
30
 }
31
 
32
+void OBSBasic::on_actionImportSceneCollection_triggered()
33
+{
34
+   char path[512];
35
+
36
+   QString home = QDir::homePath();
37
+
38
+   int ret = GetConfigPath(path, 512, "obs-studio/basic/scenes/");
39
+   if (ret <= 0) {
40
+       blog(LOG_WARNING, "Failed to get scene collection config path");
41
+       return;
42
+   }
43
+
44
+   QString file = QFileDialog::getOpenFileName(
45
+           this,
46
+           QTStr("Basic.MainMenu.SceneCollection.Import"),
47
+           home,
48
+           "JSON Files (*.json)");
49
+
50
+   QFileInfo finfo(file);
51
+   QString filename = finfo.fileName();
52
+   QFileInfo destinfo(path + filename);
53
+
54
+   if (!file.isEmpty() && !file.isNull()) {
55
+        if (!destinfo.exists()) {
56
+           QFile::copy(file, path + filename);
57
+           RefreshSceneCollections();
58
+       } else {
59
+           QMessageBox::information(this,
60
+               QTStr("Basic.MainMenu.SceneCollection.Import"),
61
+               QTStr("Basic.MainMenu.SceneCollection.Exists"));
62
+       }
63
+   }
64
+}
65
+
66
+void OBSBasic::on_actionExportSceneCollection_triggered()
67
+{
68
+   char path[512];
69
+
70
+   QString home = QDir::homePath();
71
+
72
+   QString currentFile = QT_UTF8(config_get_string(App()->GlobalConfig(),
73
+               "Basic", "SceneCollectionFile"));
74
+
75
+   int ret = GetConfigPath(path, 512, "obs-studio/basic/scenes/");
76
+   if (ret <= 0) {
77
+       blog(LOG_WARNING, "Failed to get scene collection config path");
78
+       return;
79
+   }
80
+
81
+   QString exportFile = QFileDialog::getSaveFileName(
82
+           this,
83
+           QTStr("Basic.MainMenu.SceneCollection.Export"),
84
+           home + "/" + currentFile,
85
+           "JSON Files (*.json)");
86
+
87
+   string file = QT_TO_UTF8(exportFile);
88
+
89
+   if (!exportFile.isEmpty() && !exportFile.isNull())
90
+       QFile::copy(path + currentFile + ".json", exportFile);
91
+}
92
+
93
 void OBSBasic::ChangeSceneCollection()
94
 {
95
    QAction *action = reinterpret_cast<QAction*>(sender());
96
@@ -355,7 +418,7 @@
97
    if (!action)
98
        return;
99
 
100
-   fileName = QT_TO_UTF8(action->property("fileName").value<QString>());
101
+   fileName = QT_TO_UTF8(action->property("file_name").value<QString>());
102
    if (fileName.empty())
103
        return;
104
 
105
obs-studio-0.16.6.tar.xz/UI/window-basic-main.cpp -> obs-studio-0.17.0.tar.xz/UI/window-basic-main.cpp Changed
399
 
1
@@ -847,6 +847,11 @@
2
            "Stream");
3
    config_set_default_string(basicConfig, "SimpleOutput", "RecEncoder",
4
            SIMPLE_ENCODER_X264);
5
+   config_set_default_bool(basicConfig, "SimpleOutput", "RecRB", false);
6
+   config_set_default_int(basicConfig, "SimpleOutput", "RecRBTime", 20);
7
+   config_set_default_int(basicConfig, "SimpleOutput", "RecRBSize", 512);
8
+   config_set_default_string(basicConfig, "SimpleOutput", "RecRBPrefix",
9
+           "Replay");
10
 
11
    config_set_default_bool  (basicConfig, "AdvOut", "ApplyServiceSettings",
12
            true);
13
@@ -880,6 +885,8 @@
14
    config_set_default_uint  (basicConfig, "AdvOut", "Track2Bitrate", 160);
15
    config_set_default_uint  (basicConfig, "AdvOut", "Track3Bitrate", 160);
16
    config_set_default_uint  (basicConfig, "AdvOut", "Track4Bitrate", 160);
17
+   config_set_default_uint  (basicConfig, "AdvOut", "Track5Bitrate", 160);
18
+   config_set_default_uint  (basicConfig, "AdvOut", "Track6Bitrate", 160);
19
 
20
    config_set_default_uint  (basicConfig, "Video", "BaseCX",   cx);
21
    config_set_default_uint  (basicConfig, "Video", "BaseCY",   cy);
22
@@ -1029,6 +1036,14 @@
23
    obs_leave_graphics();
24
 }
25
 
26
+void OBSBasic::ReplayBufferClicked()
27
+{
28
+   if (outputHandler->ReplayBufferActive())
29
+       StopReplayBuffer();
30
+   else
31
+       StartReplayBuffer();
32
+};
33
+
34
 void OBSBasic::ResetOutputs()
35
 {
36
    ProfileScope("OBSBasic::ResetOutputs");
37
@@ -1041,6 +1056,24 @@
38
        outputHandler.reset(advOut ?
39
            CreateAdvancedOutputHandler(this) :
40
            CreateSimpleOutputHandler(this));
41
+
42
+       delete replayBufferButton;
43
+
44
+       if (outputHandler->replayBuffer) {
45
+           replayBufferButton = new QPushButton(
46
+                   QTStr("Basic.Main.StartReplayBuffer"),
47
+                   this);
48
+           connect(replayBufferButton.data(),
49
+                   &QPushButton::clicked,
50
+                   this,
51
+                   &OBSBasic::ReplayBufferClicked);
52
+
53
+           ui->buttonsVLayout->insertWidget(2, replayBufferButton);
54
+       }
55
+
56
+       if (sysTrayReplayBuffer)
57
+           sysTrayReplayBuffer->setEnabled(
58
+                   !!outputHandler->replayBuffer);
59
    } else {
60
        outputHandler->Update();
61
    }
62
@@ -1053,6 +1086,14 @@
63
 
64
 extern obs_frontend_callbacks *InitializeAPIInterface(OBSBasic *main);
65
 
66
+#define UNSUPPORTED_ERROR \
67
+   "Failed to initialize video:\n\nRequired graphics API functionality " \
68
+   "not found.  Your GPU may not be supported."
69
+
70
+#define UNKNOWN_ERROR \
71
+   "Failed to initialize video.  Your GPU may not be supported, " \
72
+   "or your graphics drivers may need to be updated."
73
+
74
 void OBSBasic::OBSInit()
75
 {
76
    ProfileScope("OBSBasic::OBSInit");
77
@@ -1086,14 +1127,12 @@
78
    case OBS_VIDEO_MODULE_NOT_FOUND:
79
        throw "Failed to initialize video:  Graphics module not found";
80
    case OBS_VIDEO_NOT_SUPPORTED:
81
-       throw "Failed to initialize video:  Required graphics API "
82
-             "functionality not found on these drivers or "
83
-             "unavailable on this equipment";
84
+       throw UNSUPPORTED_ERROR;
85
    case OBS_VIDEO_INVALID_PARAM:
86
        throw "Failed to initialize video:  Invalid parameters";
87
    default:
88
        if (ret != OBS_VIDEO_SUCCESS)
89
-           throw "Failed to initialize video:  Unspecified error";
90
+           throw UNKNOWN_ERROR;
91
    }
92
 
93
    InitOBSCallbacks();
94
@@ -1344,9 +1383,9 @@
95
 
96
    streamingHotkeys = obs_hotkey_pair_register_frontend(
97
            "OBSBasic.StartStreaming",
98
-           Str("Basic.Hotkeys.StartStreaming"),
99
+           Str("Basic.Main.StartStreaming"),
100
            "OBSBasic.StopStreaming",
101
-           Str("Basic.Hotkeys.StopStreaming"),
102
+           Str("Basic.Main.StopStreaming"),
103
            MAKE_CALLBACK(!basic.outputHandler->StreamingActive(),
104
                basic.StartStreaming),
105
            MAKE_CALLBACK(basic.outputHandler->StreamingActive(),
106
@@ -1372,9 +1411,9 @@
107
 
108
    recordingHotkeys = obs_hotkey_pair_register_frontend(
109
            "OBSBasic.StartRecording",
110
-           Str("Basic.Hotkeys.StartRecording"),
111
+           Str("Basic.Main.StartRecording"),
112
            "OBSBasic.StopRecording",
113
-           Str("Basic.Hotkeys.StopRecording"),
114
+           Str("Basic.Main.StopRecording"),
115
            MAKE_CALLBACK(!basic.outputHandler->RecordingActive(),
116
                basic.StartRecording),
117
            MAKE_CALLBACK(basic.outputHandler->RecordingActive(),
118
@@ -1382,6 +1421,19 @@
119
            this, this);
120
    LoadHotkeyPair(recordingHotkeys,
121
            "OBSBasic.StartRecording", "OBSBasic.StopRecording");
122
+
123
+   replayBufHotkeys = obs_hotkey_pair_register_frontend(
124
+           "OBSBasic.StartReplayBuffer",
125
+           Str("Basic.Main.StartReplayBuffer"),
126
+           "OBSBasic.StopReplayBuffer",
127
+           Str("Basic.Main.StopReplayBuffer"),
128
+           MAKE_CALLBACK(!basic.outputHandler->ReplayBufferActive(),
129
+               basic.StartReplayBuffer),
130
+           MAKE_CALLBACK(basic.outputHandler->ReplayBufferActive(),
131
+               basic.StopReplayBuffer),
132
+           this, this);
133
+   LoadHotkeyPair(replayBufHotkeys,
134
+           "OBSBasic.StartReplayBuffer", "OBSBasic.StopReplayBuffer");
135
 #undef MAKE_CALLBACK
136
 
137
    auto togglePreviewProgram = [] (void *data, obs_hotkey_id,
138
@@ -1418,6 +1470,7 @@
139
 {
140
    obs_hotkey_pair_unregister(streamingHotkeys);
141
    obs_hotkey_pair_unregister(recordingHotkeys);
142
+   obs_hotkey_pair_unregister(replayBufHotkeys);
143
    obs_hotkey_unregister(forceStreamingStopHotkey);
144
    obs_hotkey_unregister(togglePreviewProgramHotkey);
145
    obs_hotkey_unregister(transitionHotkey);
146
@@ -1719,6 +1772,9 @@
147
        blog(LOG_INFO, "User added scene '%s'",
148
                obs_source_get_name(source));
149
    }
150
+
151
+   if (api)
152
+       api->on_event(OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED);
153
 }
154
 
155
 void OBSBasic::RemoveScene(OBSSource source)
156
@@ -2111,8 +2167,6 @@
157
        SetCurrentScene(source, true);
158
        obs_scene_release(scene);
159
 
160
-       if (api)
161
-           api->on_event(OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED);
162
        break;
163
    }
164
 }
165
@@ -3647,6 +3701,10 @@
166
    "==== Recording Start ==============================================="
167
 #define RECORDING_STOP \
168
    "==== Recording Stop ================================================"
169
+#define REPLAY_BUFFER_START \
170
+   "==== Replay Buffer Start ==========================================="
171
+#define REPLAY_BUFFER_STOP \
172
+   "==== Replay Buffer Stop ============================================"
173
 #define STREAMING_START \
174
    "==== Streaming Start ==============================================="
175
 #define STREAMING_STOP \
176
@@ -3963,6 +4021,7 @@
177
 
178
    if (sysTrayRecord)
179
        sysTrayRecord->setText(ui->recordButton->text());
180
+
181
    blog(LOG_INFO, RECORDING_STOP);
182
 
183
    if (code == OBS_OUTPUT_UNSUPPORTED && isVisible()) {
184
@@ -3999,6 +4058,131 @@
185
    OnDeactivate();
186
 }
187
 
188
+#define RP_NO_HOTKEY_TITLE QTStr("Output.ReplayBuffer.NoHotkey.Title")
189
+#define RP_NO_HOTKEY_TEXT  QTStr("Output.ReplayBuffer.NoHotkey.Msg")
190
+
191
+void OBSBasic::StartReplayBuffer()
192
+{
193
+   if (!outputHandler || !outputHandler->replayBuffer)
194
+       return;
195
+   if (outputHandler->ReplayBufferActive())
196
+       return;
197
+
198
+   obs_output_t *output = outputHandler->replayBuffer;
199
+   obs_data_t *hotkeys = obs_hotkeys_save_output(output);
200
+   obs_data_array_t *bindings = obs_data_get_array(hotkeys,
201
+           "ReplayBuffer.Save");
202
+   size_t count = obs_data_array_count(bindings);
203
+   obs_data_array_release(bindings);
204
+   obs_data_release(hotkeys);
205
+
206
+   if (!count) {
207
+       QMessageBox::information(this,
208
+               RP_NO_HOTKEY_TITLE,
209
+               RP_NO_HOTKEY_TEXT);
210
+       return;
211
+   }
212
+
213
+   if (api)
214
+       api->on_event(OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTING);
215
+
216
+   SaveProject();
217
+   outputHandler->StartReplayBuffer();
218
+}
219
+
220
+void OBSBasic::ReplayBufferStopping()
221
+{
222
+   if (!outputHandler || !outputHandler->replayBuffer)
223
+       return;
224
+
225
+   replayBufferButton->setText(QTStr("Basic.Main.StoppingReplayBuffer"));
226
+
227
+   if (sysTrayReplayBuffer)
228
+       sysTrayReplayBuffer->setText(replayBufferButton->text());
229
+
230
+   replayBufferStopping = true;
231
+   if (api)
232
+       api->on_event(OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPING);
233
+}
234
+
235
+void OBSBasic::StopReplayBuffer()
236
+{
237
+   if (!outputHandler || !outputHandler->replayBuffer)
238
+       return;
239
+
240
+   SaveProject();
241
+
242
+   if (outputHandler->ReplayBufferActive())
243
+       outputHandler->StopReplayBuffer(replayBufferStopping);
244
+
245
+   OnDeactivate();
246
+}
247
+
248
+void OBSBasic::ReplayBufferStart()
249
+{
250
+   if (!outputHandler || !outputHandler->replayBuffer)
251
+       return;
252
+
253
+   replayBufferButton->setText(QTStr("Basic.Main.StopReplayBuffer"));
254
+
255
+   if (sysTrayReplayBuffer)
256
+       sysTrayReplayBuffer->setText(replayBufferButton->text());
257
+
258
+   replayBufferStopping = false;
259
+   if (api)
260
+       api->on_event(OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED);
261
+
262
+   OnActivate();
263
+
264
+   blog(LOG_INFO, REPLAY_BUFFER_START);
265
+}
266
+
267
+void OBSBasic::ReplayBufferStop(int code)
268
+{
269
+   if (!outputHandler || !outputHandler->replayBuffer)
270
+       return;
271
+
272
+   replayBufferButton->setText(QTStr("Basic.Main.StartReplayBuffer"));
273
+
274
+   if (sysTrayReplayBuffer)
275
+       sysTrayReplayBuffer->setText(replayBufferButton->text());
276
+
277
+   blog(LOG_INFO, REPLAY_BUFFER_STOP);
278
+
279
+   if (code == OBS_OUTPUT_UNSUPPORTED && isVisible()) {
280
+       QMessageBox::information(this,
281
+               QTStr("Output.RecordFail.Title"),
282
+               QTStr("Output.RecordFail.Unsupported"));
283
+
284
+   } else if (code == OBS_OUTPUT_NO_SPACE && isVisible()) {
285
+       QMessageBox::information(this,
286
+               QTStr("Output.RecordNoSpace.Title"),
287
+               QTStr("Output.RecordNoSpace.Msg"));
288
+
289
+   } else if (code != OBS_OUTPUT_SUCCESS && isVisible()) {
290
+       QMessageBox::information(this,
291
+               QTStr("Output.RecordError.Title"),
292
+               QTStr("Output.RecordError.Msg"));
293
+
294
+   } else if (code == OBS_OUTPUT_UNSUPPORTED && !isVisible()) {
295
+       SysTrayNotify(QTStr("Output.RecordFail.Unsupported"),
296
+           QSystemTrayIcon::Warning);
297
+
298
+   } else if (code == OBS_OUTPUT_NO_SPACE && !isVisible()) {
299
+       SysTrayNotify(QTStr("Output.RecordNoSpace.Msg"),
300
+           QSystemTrayIcon::Warning);
301
+
302
+   } else if (code != OBS_OUTPUT_SUCCESS && !isVisible()) {
303
+       SysTrayNotify(QTStr("Output.RecordError.Msg"),
304
+           QSystemTrayIcon::Warning);
305
+   }
306
+
307
+   if (api)
308
+       api->on_event(OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED);
309
+
310
+   OnDeactivate();
311
+}
312
+
313
 void OBSBasic::on_streamButton_clicked()
314
 {
315
    if (outputHandler->StreamingActive()) {
316
@@ -4211,6 +4395,50 @@
317
    transformWindow->setAttribute(Qt::WA_DeleteOnClose, true);
318
 }
319
 
320
+static obs_transform_info copiedTransformInfo;
321
+static obs_sceneitem_crop copiedCropInfo;
322
+
323
+void OBSBasic::on_actionCopyTransform_triggered()
324
+{
325
+   auto func = [](obs_scene_t *scene, obs_sceneitem_t *item, void *param)
326
+   {
327
+       if (!obs_sceneitem_selected(item))
328
+           return true;
329
+
330
+       obs_sceneitem_defer_update_begin(item);
331
+       obs_sceneitem_get_info(item, &copiedTransformInfo);
332
+       obs_sceneitem_get_crop(item, &copiedCropInfo);
333
+       obs_sceneitem_defer_update_end(item);
334
+
335
+       UNUSED_PARAMETER(scene);
336
+       UNUSED_PARAMETER(param);
337
+       return true;
338
+   };
339
+
340
+   obs_scene_enum_items(GetCurrentScene(), func, nullptr);
341
+   ui->actionPasteTransform->setEnabled(true);
342
+}
343
+
344
+void OBSBasic::on_actionPasteTransform_triggered()
345
+{
346
+   auto func = [](obs_scene_t *scene, obs_sceneitem_t *item, void *param)
347
+   {
348
+       if (!obs_sceneitem_selected(item))
349
+           return true;
350
+
351
+       obs_sceneitem_defer_update_begin(item);
352
+       obs_sceneitem_set_info(item, &copiedTransformInfo);
353
+       obs_sceneitem_set_crop(item, &copiedCropInfo);
354
+       obs_sceneitem_defer_update_end(item);
355
+
356
+       UNUSED_PARAMETER(scene);
357
+       UNUSED_PARAMETER(param);
358
+       return true;
359
+   };
360
+
361
+   obs_scene_enum_items(GetCurrentScene(), func, nullptr);
362
+}
363
+
364
 void OBSBasic::on_actionResetTransform_triggered()
365
 {
366
    auto func = [] (obs_scene_t *scene, obs_sceneitem_t *item, void *param)
367
@@ -4693,9 +4921,14 @@
368
            trayIcon);
369
    sysTrayRecord = new QAction(QTStr("Basic.Main.StartRecording"),
370
            trayIcon);
371
+   sysTrayReplayBuffer = new QAction(QTStr("Basic.Main.StartReplayBuffer"),
372
+           trayIcon);
373
    exit = new QAction(QTStr("Exit"),
374
            trayIcon);
375
 
376
+   if (outputHandler && !outputHandler->replayBuffer)
377
+       sysTrayReplayBuffer->setEnabled(false);
378
+
379
    connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
380
            this,
381
            SLOT(IconActivated(QSystemTrayIcon::ActivationReason)));
382
@@ -4705,6 +4938,8 @@
383
            this, SLOT(on_streamButton_clicked()));
384
    connect(sysTrayRecord, SIGNAL(triggered()),
385
            this, SLOT(on_recordButton_clicked()));
386
+   connect(sysTrayReplayBuffer.data(), &QAction::triggered,
387
+           this, &OBSBasic::ReplayBufferClicked);
388
    connect(exit, SIGNAL(triggered()),
389
            this, SLOT(close()));
390
 
391
@@ -4712,6 +4947,7 @@
392
    trayMenu->addAction(showHide);
393
    trayMenu->addAction(sysTrayStream);
394
    trayMenu->addAction(sysTrayRecord);
395
+   trayMenu->addAction(sysTrayReplayBuffer);
396
    trayMenu->addAction(exit);
397
    trayIcon->setContextMenu(trayMenu);
398
 }
399
obs-studio-0.16.6.tar.xz/UI/window-basic-main.hpp -> obs-studio-0.17.0.tar.xz/UI/window-basic-main.hpp Changed
88
 
1
@@ -86,6 +86,7 @@
2
    friend class OBSBasicPreview;
3
    friend class OBSBasicStatusBar;
4
    friend class OBSBasicSourceSelect;
5
+   friend class OBSBasicSettings;
6
    friend struct OBSStudioAPI;
7
 
8
    enum class MoveDir {
9
@@ -130,6 +131,7 @@
10
    std::unique_ptr<BasicOutputHandler> outputHandler;
11
    bool streamingStopping = false;
12
    bool recordingStopping = false;
13
+   bool replayBufferStopping = false;
14
 
15
    gs_vertbuffer_t *box = nullptr;
16
    gs_vertbuffer_t *boxLeft = nullptr;
17
@@ -151,9 +153,12 @@
18
 
19
    QPointer<QMenu> startStreamMenu;
20
 
21
+   QPointer<QPushButton> replayBufferButton;
22
+
23
    QPointer<QSystemTrayIcon> trayIcon;
24
    QPointer<QAction>         sysTrayStream;
25
    QPointer<QAction>         sysTrayRecord;
26
+   QPointer<QAction>         sysTrayReplayBuffer;
27
    QPointer<QAction>         showHide;
28
    QPointer<QAction>         exit;
29
    QPointer<QMenu>           trayMenu;
30
@@ -244,7 +249,8 @@
31
 
32
    QListWidgetItem *GetTopSelectedSourceItem();
33
 
34
-   obs_hotkey_pair_id streamingHotkeys, recordingHotkeys;
35
+   obs_hotkey_pair_id streamingHotkeys, recordingHotkeys,
36
+                      replayBufHotkeys;
37
    obs_hotkey_id forceStreamingStopHotkey;
38
 
39
    void InitDefaultTransitions();
40
@@ -313,6 +319,8 @@
41
    void dragMoveEvent(QDragMoveEvent *event) override;
42
    void dropEvent(QDropEvent *event) override;
43
 
44
+   void ReplayBufferClicked();
45
+
46
 public slots:
47
    void StartStreaming();
48
    void StopStreaming();
49
@@ -332,6 +340,13 @@
50
    void RecordStopping();
51
    void RecordingStop(int code);
52
 
53
+   void StartReplayBuffer();
54
+   void StopReplayBuffer();
55
+
56
+   void ReplayBufferStart();
57
+   void ReplayBufferStopping();
58
+   void ReplayBufferStop(int code);
59
+
60
    void SaveProjectDeferred();
61
    void SaveProject();
62
 
63
@@ -483,6 +498,8 @@
64
    void on_actionCheckForUpdates_triggered();
65
 
66
    void on_actionEditTransform_triggered();
67
+   void on_actionCopyTransform_triggered();
68
+   void on_actionPasteTransform_triggered();
69
    void on_actionRotate90CW_triggered();
70
    void on_actionRotate90CCW_triggered();
71
    void on_actionRotate180_triggered();
72
@@ -535,11 +552,15 @@
73
    void on_actionDupSceneCollection_triggered();
74
    void on_actionRenameSceneCollection_triggered();
75
    void on_actionRemoveSceneCollection_triggered();
76
+   void on_actionImportSceneCollection_triggered();
77
+   void on_actionExportSceneCollection_triggered();
78
 
79
    void on_actionNewProfile_triggered();
80
    void on_actionDupProfile_triggered();
81
    void on_actionRenameProfile_triggered();
82
    void on_actionRemoveProfile_triggered();
83
+   void on_actionImportProfile_triggered();
84
+   void on_actionExportProfile_triggered();
85
 
86
    void on_actionShowSettingsFolder_triggered();
87
    void on_actionShowProfileFolder_triggered();
88
obs-studio-0.16.6.tar.xz/UI/window-basic-settings.cpp -> obs-studio-0.17.0.tar.xz/UI/window-basic-settings.cpp Changed
417
 
1
@@ -44,6 +44,7 @@
2
 #include "qt-wrappers.hpp"
3
 #include "window-basic-main.hpp"
4
 #include "window-basic-settings.hpp"
5
+#include "window-basic-main-outputs.hpp"
6
 
7
 #include <util/platform.h>
8
 
9
@@ -261,7 +262,8 @@
10
 
11
    PopulateAACBitrates({ui->simpleOutputABitrate,
12
            ui->advOutTrack1Bitrate, ui->advOutTrack2Bitrate,
13
-           ui->advOutTrack3Bitrate, ui->advOutTrack4Bitrate});
14
+           ui->advOutTrack3Bitrate, ui->advOutTrack4Bitrate,
15
+           ui->advOutTrack5Bitrate, ui->advOutTrack6Bitrate});
16
 
17
    ui->listWidget->setAttribute(Qt::WA_MacShowFocusRect, false);
18
 
19
@@ -299,6 +301,9 @@
20
    HookWidget(ui->simpleOutRecQuality,  COMBO_CHANGED,  OUTPUTS_CHANGED);
21
    HookWidget(ui->simpleOutRecEncoder,  COMBO_CHANGED,  OUTPUTS_CHANGED);
22
    HookWidget(ui->simpleOutMuxCustom,   EDIT_CHANGED,   OUTPUTS_CHANGED);
23
+   HookWidget(ui->simpleReplayBuf,      CHECK_CHANGED,  OUTPUTS_CHANGED);
24
+   HookWidget(ui->simpleRBSecMax,       SCROLL_CHANGED, OUTPUTS_CHANGED);
25
+   HookWidget(ui->simpleRBMegsMax,      SCROLL_CHANGED, OUTPUTS_CHANGED);
26
    HookWidget(ui->advOutEncoder,        COMBO_CHANGED,  OUTPUTS_CHANGED);
27
    HookWidget(ui->advOutUseRescale,     CHECK_CHANGED,  OUTPUTS_CHANGED);
28
    HookWidget(ui->advOutRescale,        CBEDIT_CHANGED, OUTPUTS_CHANGED);
29
@@ -306,6 +311,8 @@
30
    HookWidget(ui->advOutTrack2,         CHECK_CHANGED,  OUTPUTS_CHANGED);
31
    HookWidget(ui->advOutTrack3,         CHECK_CHANGED,  OUTPUTS_CHANGED);
32
    HookWidget(ui->advOutTrack4,         CHECK_CHANGED,  OUTPUTS_CHANGED);
33
+   HookWidget(ui->advOutTrack5,         CHECK_CHANGED,  OUTPUTS_CHANGED);
34
+   HookWidget(ui->advOutTrack6,         CHECK_CHANGED,  OUTPUTS_CHANGED);
35
    HookWidget(ui->advOutApplyService,   CHECK_CHANGED,  OUTPUTS_CHANGED);
36
    HookWidget(ui->advOutRecType,        COMBO_CHANGED,  OUTPUTS_CHANGED);
37
    HookWidget(ui->advOutRecPath,        EDIT_CHANGED,   OUTPUTS_CHANGED);
38
@@ -319,6 +326,8 @@
39
    HookWidget(ui->advOutRecTrack2,      CHECK_CHANGED,  OUTPUTS_CHANGED);
40
    HookWidget(ui->advOutRecTrack3,      CHECK_CHANGED,  OUTPUTS_CHANGED);
41
    HookWidget(ui->advOutRecTrack4,      CHECK_CHANGED,  OUTPUTS_CHANGED);
42
+   HookWidget(ui->advOutRecTrack5,      CHECK_CHANGED,  OUTPUTS_CHANGED);
43
+   HookWidget(ui->advOutRecTrack6,      CHECK_CHANGED,  OUTPUTS_CHANGED);
44
    HookWidget(ui->advOutFFType,         COMBO_CHANGED,  OUTPUTS_CHANGED);
45
    HookWidget(ui->advOutFFRecPath,      EDIT_CHANGED,   OUTPUTS_CHANGED);
46
    HookWidget(ui->advOutFFNoSpace,      CHECK_CHANGED,  OUTPUTS_CHANGED);
47
@@ -335,6 +344,8 @@
48
    HookWidget(ui->advOutFFTrack2,       CHECK_CHANGED,  OUTPUTS_CHANGED);
49
    HookWidget(ui->advOutFFTrack3,       CHECK_CHANGED,  OUTPUTS_CHANGED);
50
    HookWidget(ui->advOutFFTrack4,       CHECK_CHANGED,  OUTPUTS_CHANGED);
51
+   HookWidget(ui->advOutFFTrack5,       CHECK_CHANGED,  OUTPUTS_CHANGED);
52
+   HookWidget(ui->advOutFFTrack6,       CHECK_CHANGED,  OUTPUTS_CHANGED);
53
    HookWidget(ui->advOutFFAEncoder,     COMBO_CHANGED,   OUTPUTS_CHANGED);
54
    HookWidget(ui->advOutFFACfg,         EDIT_CHANGED,   OUTPUTS_CHANGED);
55
    HookWidget(ui->advOutTrack1Bitrate,  COMBO_CHANGED,  OUTPUTS_CHANGED);
56
@@ -345,6 +356,10 @@
57
    HookWidget(ui->advOutTrack3Name,     EDIT_CHANGED,   OUTPUTS_CHANGED);
58
    HookWidget(ui->advOutTrack4Bitrate,  COMBO_CHANGED,  OUTPUTS_CHANGED);
59
    HookWidget(ui->advOutTrack4Name,     EDIT_CHANGED,   OUTPUTS_CHANGED);
60
+   HookWidget(ui->advOutTrack5Bitrate,  COMBO_CHANGED,  OUTPUTS_CHANGED);
61
+   HookWidget(ui->advOutTrack5Name,     EDIT_CHANGED,   OUTPUTS_CHANGED);
62
+   HookWidget(ui->advOutTrack6Bitrate,  COMBO_CHANGED,  OUTPUTS_CHANGED);
63
+   HookWidget(ui->advOutTrack6Name,     EDIT_CHANGED,   OUTPUTS_CHANGED);
64
    HookWidget(ui->channelSetup,         COMBO_CHANGED,  AUDIO_RESTART);
65
    HookWidget(ui->sampleRate,           COMBO_CHANGED,  AUDIO_RESTART);
66
    HookWidget(ui->desktopAudioDevice1,  COMBO_CHANGED,  AUDIO_CHANGED);
67
@@ -370,6 +385,8 @@
68
    HookWidget(ui->resetOSXVSync,        CHECK_CHANGED,  ADV_CHANGED);
69
    HookWidget(ui->filenameFormatting,   EDIT_CHANGED,   ADV_CHANGED);
70
    HookWidget(ui->overwriteIfExists,    CHECK_CHANGED,  ADV_CHANGED);
71
+   HookWidget(ui->simpleRBPrefix,       EDIT_CHANGED,   ADV_CHANGED);
72
+   HookWidget(ui->simpleRBSuffix,       EDIT_CHANGED,   ADV_CHANGED);
73
    HookWidget(ui->streamDelayEnable,    CHECK_CHANGED,  ADV_CHANGED);
74
    HookWidget(ui->streamDelaySec,       SCROLL_CHANGED, ADV_CHANGED);
75
    HookWidget(ui->streamDelayPreserve,  CHECK_CHANGED,  ADV_CHANGED);
76
@@ -451,6 +468,10 @@
77
            this, SLOT(UpdateStreamDelayEstimate()));
78
    connect(ui->advOutTrack4Bitrate, SIGNAL(currentIndexChanged(int)),
79
            this, SLOT(UpdateStreamDelayEstimate()));
80
+   connect(ui->advOutTrack5Bitrate, SIGNAL(currentIndexChanged(int)),
81
+           this, SLOT(UpdateStreamDelayEstimate()));
82
+   connect(ui->advOutTrack6Bitrate, SIGNAL(currentIndexChanged(int)),
83
+           this, SLOT(UpdateStreamDelayEstimate()));
84
 
85
    //Apply button disabled until change.
86
    EnableApplyButton(false);
87
@@ -525,6 +546,14 @@
88
            this, SLOT(SimpleRecordingEncoderChanged()));
89
    connect(ui->simpleOutEnforce, SIGNAL(toggled(bool)),
90
            this, SLOT(SimpleRecordingEncoderChanged()));
91
+   connect(ui->simpleReplayBuf, SIGNAL(toggled(bool)),
92
+           this, SLOT(SimpleReplayBufferChanged()));
93
+   connect(ui->simpleOutputVBitrate, SIGNAL(valueChanged(int)),
94
+           this, SLOT(SimpleReplayBufferChanged()));
95
+   connect(ui->simpleOutputABitrate, SIGNAL(currentIndexChanged(int)),
96
+           this, SLOT(SimpleReplayBufferChanged()));
97
+   connect(ui->simpleRBSecMax, SIGNAL(valueChanged(int)),
98
+           this, SLOT(SimpleReplayBufferChanged()));
99
    connect(ui->listWidget, SIGNAL(currentRowChanged(int)),
100
            this, SLOT(SimpleRecordingEncoderChanged()));
101
 
102
@@ -553,6 +582,10 @@
103
            this, SLOT(AdvOutRecCheckWarnings()));
104
    connect(ui->advOutRecTrack4, SIGNAL(clicked()),
105
            this, SLOT(AdvOutRecCheckWarnings()));
106
+   connect(ui->advOutRecTrack5, SIGNAL(clicked()),
107
+           this, SLOT(AdvOutRecCheckWarnings()));
108
+   connect(ui->advOutRecTrack6, SIGNAL(clicked()),
109
+           this, SLOT(AdvOutRecCheckWarnings()));
110
    AdvOutRecCheckWarnings();
111
 
112
    SimpleRecordingQualityChanged();
113
@@ -1216,6 +1249,12 @@
114
            "RecEncoder");
115
    const char *muxCustom = config_get_string(main->Config(),
116
            "SimpleOutput", "MuxerCustom");
117
+   bool replayBuf = config_get_bool(main->Config(), "SimpleOutput",
118
+           "RecRB");
119
+   int rbTime = config_get_int(main->Config(), "SimpleOutput",
120
+           "RecRBTime");
121
+   int rbSize = config_get_int(main->Config(), "SimpleOutput",
122
+           "RecRBSize");
123
 
124
    curPreset = preset;
125
    curQSVPreset = qsvPreset;
126
@@ -1252,6 +1291,10 @@
127
 
128
    ui->simpleOutMuxCustom->setText(muxCustom);
129
 
130
+   ui->simpleReplayBuf->setChecked(replayBuf);
131
+   ui->simpleRBSecMax->setValue(rbTime);
132
+   ui->simpleRBMegsMax->setValue(rbSize);
133
+
134
    SimpleStreamingEncoderChanged();
135
 }
136
 
137
@@ -1284,6 +1327,8 @@
138
    case 2: ui->advOutTrack2->setChecked(true); break;
139
    case 3: ui->advOutTrack3->setChecked(true); break;
140
    case 4: ui->advOutTrack4->setChecked(true); break;
141
+   case 5: ui->advOutTrack5->setChecked(true); break;
142
+   case 6: ui->advOutTrack6->setChecked(true); break;
143
    }
144
 }
145
 
146
@@ -1378,6 +1423,8 @@
147
    ui->advOutRecTrack2->setChecked(tracks & (1<<1));
148
    ui->advOutRecTrack3->setChecked(tracks & (1<<2));
149
    ui->advOutRecTrack4->setChecked(tracks & (1<<3));
150
+   ui->advOutRecTrack5->setChecked(tracks & (1<<4));
151
+   ui->advOutRecTrack6->setChecked(tracks & (1<<5));
152
 }
153
 
154
 void OBSBasicSettings::LoadAdvOutputRecordingEncoderProperties()
155
@@ -1492,6 +1539,8 @@
156
    case 2: ui->advOutFFTrack2->setChecked(true); break;
157
    case 3: ui->advOutFFTrack3->setChecked(true); break;
158
    case 4: ui->advOutFFTrack4->setChecked(true); break;
159
+   case 5: ui->advOutFFTrack5->setChecked(true); break;
160
+   case 6: ui->advOutFFTrack6->setChecked(true); break;
161
    }
162
 }
163
 
164
@@ -1505,6 +1554,10 @@
165
            "Track3Bitrate");
166
    int track4Bitrate = config_get_uint(main->Config(), "AdvOut",
167
            "Track4Bitrate");
168
+   int track5Bitrate = config_get_uint(main->Config(), "AdvOut",
169
+           "Track5Bitrate");
170
+   int track6Bitrate = config_get_uint(main->Config(), "AdvOut",
171
+           "Track6Bitrate");
172
    const char *name1 = config_get_string(main->Config(), "AdvOut",
173
            "Track1Name");
174
    const char *name2 = config_get_string(main->Config(), "AdvOut",
175
@@ -1513,11 +1566,17 @@
176
            "Track3Name");
177
    const char *name4 = config_get_string(main->Config(), "AdvOut",
178
            "Track4Name");
179
+   const char *name5 = config_get_string(main->Config(), "AdvOut",
180
+           "Track5Name");
181
+   const char *name6 = config_get_string(main->Config(), "AdvOut",
182
+           "Track6Name");
183
 
184
    track1Bitrate = FindClosestAvailableAACBitrate(track1Bitrate);
185
    track2Bitrate = FindClosestAvailableAACBitrate(track2Bitrate);
186
    track3Bitrate = FindClosestAvailableAACBitrate(track3Bitrate);
187
    track4Bitrate = FindClosestAvailableAACBitrate(track4Bitrate);
188
+   track5Bitrate = FindClosestAvailableAACBitrate(track5Bitrate);
189
+   track6Bitrate = FindClosestAvailableAACBitrate(track6Bitrate);
190
 
191
    SetComboByName(ui->advOutTrack1Bitrate,
192
            std::to_string(track1Bitrate).c_str());
193
@@ -1527,11 +1586,17 @@
194
            std::to_string(track3Bitrate).c_str());
195
    SetComboByName(ui->advOutTrack4Bitrate,
196
            std::to_string(track4Bitrate).c_str());
197
+   SetComboByName(ui->advOutTrack5Bitrate,
198
+           std::to_string(track5Bitrate).c_str());
199
+   SetComboByName(ui->advOutTrack6Bitrate,
200
+           std::to_string(track6Bitrate).c_str());
201
 
202
    ui->advOutTrack1Name->setText(name1);
203
    ui->advOutTrack2Name->setText(name2);
204
    ui->advOutTrack3Name->setText(name3);
205
    ui->advOutTrack4Name->setText(name4);
206
+   ui->advOutTrack5Name->setText(name5);
207
+   ui->advOutTrack6Name->setText(name6);
208
 }
209
 
210
 void OBSBasicSettings::LoadOutputSettings()
211
@@ -1554,6 +1619,8 @@
212
    if (video_output_active(obs_get_video())) {
213
        ui->outputMode->setEnabled(false);
214
        ui->outputModeLabel->setEnabled(false);
215
+       ui->simpleRecordingGroupBox->setEnabled(false);
216
+       ui->replayBufferGroupBox->setEnabled(false);
217
        ui->advOutTopContainer->setEnabled(false);
218
        ui->advOutRecTopContainer->setEnabled(false);
219
        ui->advOutRecTypeContainer->setEnabled(false);
220
@@ -1586,6 +1653,8 @@
221
        ui->advOutFFTrack2->setEnabled(enabled);
222
        ui->advOutFFTrack3->setEnabled(enabled);
223
        ui->advOutFFTrack4->setEnabled(enabled);
224
+       ui->advOutFFTrack5->setEnabled(enabled);
225
+       ui->advOutFFTrack6->setEnabled(enabled);
226
    default:
227
        break;
228
    }
229
@@ -1845,6 +1914,10 @@
230
            "OverwriteIfExists");
231
    const char *bindIP = config_get_string(main->Config(), "Output",
232
            "BindIP");
233
+   const char *rbPrefix = config_get_string(main->Config(), "SimpleOutput",
234
+           "RecRBPrefix");
235
+   const char *rbSuffix = config_get_string(main->Config(), "SimpleOutput",
236
+           "RecRBSuffix");
237
 
238
    loading = true;
239
 
240
@@ -1852,6 +1925,8 @@
241
 
242
    ui->filenameFormatting->setText(filename);
243
    ui->overwriteIfExists->setChecked(overwriteIfExists);
244
+   ui->simpleRBPrefix->setText(rbPrefix);
245
+   ui->simpleRBSuffix->setText(rbSuffix);
246
 
247
    ui->reconnectEnable->setChecked(reconnect);
248
    ui->reconnectRetryDelay->setValue(retryDelay);
249
@@ -2358,6 +2433,8 @@
250
    SaveCombo(ui->colorSpace, "Video", "ColorSpace");
251
    SaveComboData(ui->colorRange, "Video", "ColorRange");
252
    SaveEdit(ui->filenameFormatting, "Output", "FilenameFormatting");
253
+   SaveEdit(ui->simpleRBPrefix, "SimpleOutput", "RecRBPrefix");
254
+   SaveEdit(ui->simpleRBSuffix, "SimpleOutput", "RecRBSuffix");
255
    SaveCheckBox(ui->overwriteIfExists, "Output", "OverwriteIfExists");
256
    SaveCheckBox(ui->streamDelayEnable, "Output", "DelayEnable");
257
    SaveSpinBox(ui->streamDelaySec, "Output", "DelaySec");
258
@@ -2406,12 +2483,16 @@
259
        QAbstractButton *check1,
260
        QAbstractButton *check2,
261
        QAbstractButton *check3,
262
-       QAbstractButton *check4)
263
+       QAbstractButton *check4,
264
+       QAbstractButton *check5,
265
+       QAbstractButton *check6)
266
 {
267
    if (check1->isChecked()) config_set_int(config, section, name, 1);
268
    else if (check2->isChecked()) config_set_int(config, section, name, 2);
269
    else if (check3->isChecked()) config_set_int(config, section, name, 3);
270
    else if (check4->isChecked()) config_set_int(config, section, name, 4);
271
+   else if (check5->isChecked()) config_set_int(config, section, name, 5);
272
+   else if (check6->isChecked()) config_set_int(config, section, name, 6);
273
 }
274
 
275
 void OBSBasicSettings::SaveFormat(QComboBox *combo)
276
@@ -2488,6 +2569,9 @@
277
    SaveComboData(ui->simpleOutRecQuality, "SimpleOutput", "RecQuality");
278
    SaveComboData(ui->simpleOutRecEncoder, "SimpleOutput", "RecEncoder");
279
    SaveEdit(ui->simpleOutMuxCustom, "SimpleOutput", "MuxerCustom");
280
+   SaveCheckBox(ui->simpleReplayBuf, "SimpleOutput", "RecRB");
281
+   SaveSpinBox(ui->simpleRBSecMax, "SimpleOutput", "RecRBTime");
282
+   SaveSpinBox(ui->simpleRBMegsMax, "SimpleOutput", "RecRBSize");
283
 
284
    curAdvStreamEncoder = GetComboData(ui->advOutEncoder);
285
 
286
@@ -2497,7 +2581,8 @@
287
    SaveCombo(ui->advOutRescale, "AdvOut", "RescaleRes");
288
    SaveTrackIndex(main->Config(), "AdvOut", "TrackIndex",
289
            ui->advOutTrack1, ui->advOutTrack2,
290
-           ui->advOutTrack3, ui->advOutTrack4);
291
+           ui->advOutTrack3, ui->advOutTrack4,
292
+           ui->advOutTrack5, ui->advOutTrack6);
293
 
294
    config_set_string(main->Config(), "AdvOut", "RecType",
295
            RecTypeFromIdx(ui->advOutRecType->currentIndex()));
296
@@ -2516,7 +2601,9 @@
297
            (ui->advOutRecTrack1->isChecked() ? (1<<0) : 0) |
298
            (ui->advOutRecTrack2->isChecked() ? (1<<1) : 0) |
299
            (ui->advOutRecTrack3->isChecked() ? (1<<2) : 0) |
300
-           (ui->advOutRecTrack4->isChecked() ? (1<<3) : 0));
301
+           (ui->advOutRecTrack4->isChecked() ? (1<<3) : 0) |
302
+           (ui->advOutRecTrack5->isChecked() ? (1<<4) : 0) |
303
+           (ui->advOutRecTrack6->isChecked() ? (1<<5) : 0));
304
 
305
    config_set_bool(main->Config(), "AdvOut", "FFOutputToFile",
306
            ui->advOutFFType->currentIndex() == 0 ? true : false);
307
@@ -2535,16 +2622,21 @@
308
    SaveEdit(ui->advOutFFACfg, "AdvOut", "FFACustom");
309
    SaveTrackIndex(main->Config(), "AdvOut", "FFAudioTrack",
310
            ui->advOutFFTrack1, ui->advOutFFTrack2,
311
-           ui->advOutFFTrack3, ui->advOutFFTrack4);
312
+           ui->advOutFFTrack3, ui->advOutFFTrack4,
313
+           ui->advOutFFTrack5, ui->advOutFFTrack6);
314
 
315
    SaveCombo(ui->advOutTrack1Bitrate, "AdvOut", "Track1Bitrate");
316
    SaveCombo(ui->advOutTrack2Bitrate, "AdvOut", "Track2Bitrate");
317
    SaveCombo(ui->advOutTrack3Bitrate, "AdvOut", "Track3Bitrate");
318
    SaveCombo(ui->advOutTrack4Bitrate, "AdvOut", "Track4Bitrate");
319
+   SaveCombo(ui->advOutTrack5Bitrate, "AdvOut", "Track5Bitrate");
320
+   SaveCombo(ui->advOutTrack6Bitrate, "AdvOut", "Track6Bitrate");
321
    SaveEdit(ui->advOutTrack1Name, "AdvOut", "Track1Name");
322
    SaveEdit(ui->advOutTrack2Name, "AdvOut", "Track2Name");
323
    SaveEdit(ui->advOutTrack3Name, "AdvOut", "Track3Name");
324
    SaveEdit(ui->advOutTrack4Name, "AdvOut", "Track4Name");
325
+   SaveEdit(ui->advOutTrack5Name, "AdvOut", "Track5Name");
326
+   SaveEdit(ui->advOutTrack6Name, "AdvOut", "Track6Name");
327
 
328
    WriteJsonData(streamEncoderProps, "streamEncoder.json");
329
    WriteJsonData(recordEncoderProps, "recordEncoder.json");
330
@@ -2635,6 +2727,18 @@
331
        obs_data_release(data);
332
        obs_data_array_release(array);
333
    }
334
+
335
+   if (!main->outputHandler || !main->outputHandler->replayBuffer)
336
+       return;
337
+
338
+   const char *id = obs_obj_get_id(main->outputHandler->replayBuffer);
339
+   if (strcmp(id, "replay_buffer") == 0) {
340
+       obs_data_t *hotkeys = obs_hotkeys_save_output(
341
+               main->outputHandler->replayBuffer);
342
+       config_set_string(config, "Hotkeys", "ReplayBuffer",
343
+               obs_data_get_json(hotkeys));
344
+       obs_data_release(hotkeys);
345
+   }
346
 }
347
 
348
 #define MINOR_SEPARATOR \
349
@@ -3134,7 +3238,9 @@
350
        Checked(ui->advOutRecTrack1) +
351
        Checked(ui->advOutRecTrack2) +
352
        Checked(ui->advOutRecTrack3) +
353
-       Checked(ui->advOutRecTrack4);
354
+       Checked(ui->advOutRecTrack4) +
355
+       Checked(ui->advOutRecTrack5) +
356
+       Checked(ui->advOutRecTrack6);
357
    const char *objectName = nullptr;
358
 
359
    if (tracks == 0) {
360
@@ -3192,6 +3298,8 @@
361
    case 2: aBitrateText = ui->advOutTrack2Bitrate->currentText(); break;
362
    case 3: aBitrateText = ui->advOutTrack3Bitrate->currentText(); break;
363
    case 4: aBitrateText = ui->advOutTrack4Bitrate->currentText(); break;
364
+   case 5: aBitrateText = ui->advOutTrack5Bitrate->currentText(); break;
365
+   case 6: aBitrateText = ui->advOutTrack6Bitrate->currentText(); break;
366
    }
367
 
368
    int seconds = ui->streamDelaySec->value();
369
@@ -3291,6 +3399,7 @@
370
    ui->simpleOutRecFormatLabel->setVisible(!losslessQuality);
371
 
372
    SimpleRecordingEncoderChanged();
373
+   SimpleReplayBufferChanged();
374
 }
375
 
376
 void OBSBasicSettings::SimpleStreamingEncoderChanged()
377
@@ -3363,6 +3472,39 @@
378
    ui->simpleOutPreset->setCurrentIndex(idx);
379
 }
380
 
381
+#define ESTIMATE_STR "Basic.Settings.Output.ReplayBuffer.Estimate"
382
+#define ESTIMATE_UNKNOWN_STR \
383
+   "Basic.Settings.Output.ReplayBuffer.EstimateUnknown"
384
+
385
+void OBSBasicSettings::SimpleReplayBufferChanged()
386
+{
387
+   QString qual = ui->simpleOutRecQuality->currentData().toString();
388
+   bool replayBufferEnabled = ui->simpleReplayBuf->isChecked();
389
+   bool lossless = qual == "Lossless";
390
+   bool streamQuality = qual == "Stream";
391
+
392
+   ui->simpleRBMegsMax->setVisible(!streamQuality);
393
+   ui->simpleRBMegsMaxLabel->setVisible(!streamQuality);
394
+
395
+   int vbitrate = ui->simpleOutputVBitrate->value();
396
+   int abitrate = ui->simpleOutputABitrate->currentText().toInt();
397
+   int seconds = ui->simpleRBSecMax->value();
398
+
399
+   int64_t memMB = int64_t(seconds) * int64_t(vbitrate + abitrate) *
400
+       1000 / 8 / 1024 / 1024;
401
+   if (memMB < 1) memMB = 1;
402
+
403
+   if (streamQuality)
404
+       ui->simpleRBEstimate->setText(
405
+               QTStr(ESTIMATE_STR).arg(
406
+                   QString::number(int(memMB))));
407
+   else
408
+       ui->simpleRBEstimate->setText(QTStr(ESTIMATE_UNKNOWN_STR));
409
+
410
+   ui->replayBufferGroupBox->setVisible(!lossless && replayBufferEnabled);
411
+   ui->simpleReplayBuf->setVisible(!lossless);
412
+}
413
+
414
 #define SIMPLE_OUTPUT_WARNING(str) \
415
    QTStr("Basic.Settings.Output.Simple.Warn." str)
416
 
417
obs-studio-0.16.6.tar.xz/UI/window-basic-settings.hpp -> obs-studio-0.17.0.tar.xz/UI/window-basic-settings.hpp Changed
10
 
1
@@ -290,6 +290,8 @@
2
    void SimpleRecordingEncoderChanged();
3
    void SimpleRecordingQualityLosslessWarning(int idx);
4
 
5
+   void SimpleReplayBufferChanged();
6
+
7
    void SimpleStreamingEncoderChanged();
8
 
9
 protected:
10
obs-studio-0.16.6.tar.xz/UI/window-basic-transform.cpp -> obs-studio-0.17.0.tar.xz/UI/window-basic-transform.cpp Changed
14
 
1
@@ -56,10 +56,10 @@
2
    HookWidget(ui->cropTop,      ISCROLL_CHANGED, SLOT(OnCropChanged()));
3
    HookWidget(ui->cropBottom,   ISCROLL_CHANGED, SLOT(OnCropChanged()));
4
 
5
+   ui->buttonBox->button(QDialogButtonBox::Close)->setDefault(true);
6
+
7
    connect(ui->buttonBox->button(QDialogButtonBox::Reset),
8
        SIGNAL(clicked()), this, SLOT(on_resetButton_clicked()));
9
-   connect(ui->buttonBox,
10
-       SIGNAL(rejected()), this, SLOT(close()));
11
 
12
    installEventFilter(CreateShortcutFilter());
13
 
14
obs-studio-0.16.6.tar.xz/cmake/osxbundle/fixup_bundle.sh -> obs-studio-0.17.0.tar.xz/cmake/osxbundle/fixup_bundle.sh Changed
20
 
1
@@ -9,7 +9,9 @@
2
 
3
 function buildlist() {
4
    otool -L "$@" | 
5
-       grep -E "(opt|Users)" |
6
+       grep -E '^\s+/' |
7
+       grep -vE '^\s+/System/' |
8
+       grep -vE '^\s+/usr/lib/' |
9
        perl -pe 's|^\s+(/.*)\s\(.*$|$1|' |
10
        grep -vE ":$" |
11
        sort -u
12
@@ -34,6 +36,7 @@
13
 
14
    INTOOL_CALL+=(-change "$lib" "$LDEST/$libname")
15
    cp "$lib" "$DEST/$libname"
16
+   chmod 644 "$DEST/$libname"
17
 
18
    echo "Fixing up dependency: $libname"
19
 done
20
obs-studio-0.16.6.tar.xz/deps/CMakeLists.txt -> obs-studio-0.17.0.tar.xz/deps/CMakeLists.txt Changed
12
 
1
@@ -8,6 +8,10 @@
2
 add_subdirectory(libff)
3
 add_subdirectory(file-updater)
4
 
5
+if(BUILD_CAPTIONS)
6
+   add_subdirectory(libcaption)
7
+endif()
8
+
9
 find_package(Jansson 2.5 QUIET)
10
 
11
 if(NOT JANSSON_FOUND)
12
obs-studio-0.16.6.tar.xz/deps/ipc-util/CMakeLists.txt -> obs-studio-0.17.0.tar.xz/deps/ipc-util/CMakeLists.txt Changed
12
 
1
@@ -22,6 +22,10 @@
2
        ipc-util/pipe-posix.c)
3
 endif()
4
 
5
+if(MSVC)
6
+   add_compile_options("$<$<CONFIG:RelWithDebInfo>:/MT>")
7
+endif()
8
+
9
 add_library(ipc-util STATIC
10
    ${ipc-util_SOURCES}
11
    ${ipc-util_HEADERS})
12
obs-studio-0.17.0.tar.xz/deps/libcaption Added
2
 
1
+(directory)
2
obs-studio-0.17.0.tar.xz/deps/libcaption/CMakeLists.txt Added
36
 
1
@@ -0,0 +1,34 @@
2
+cmake_minimum_required(VERSION 2.8)
3
+project(libcaption)
4
+add_definitions(-D__STDC_CONSTANT_MACROS)
5
+if (WIN32)
6
+  add_definitions(-D_CRT_SECURE_NO_WARNINGS)
7
+endif()
8
+
9
+# Don't need to prefix local includes with "caption/*"
10
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/caption)
11
+
12
+set(CAPTION_SOURCES
13
+  src/utf8.c
14
+  src/srt.c
15
+  src/scc.c
16
+  src/avc.c
17
+  src/xds.c
18
+  src/cea708.c
19
+  src/caption.c
20
+  src/eia608_charmap.c
21
+  src/eia608.c
22
+)
23
+
24
+set(CAPTION_HEADERS
25
+  caption/utf8.h
26
+  caption/sei.h
27
+  caption/scc.h
28
+  caption/avc.c
29
+  caption/cea708.h
30
+  caption/eia608.h
31
+  caption/caption.h
32
+  caption/eia608_charmap.h
33
+)
34
+
35
+add_library(caption STATIC ${CAPTION_SOURCES})
36
obs-studio-0.17.0.tar.xz/deps/libcaption/Doxyfile.in Added
2408
 
1
@@ -0,0 +1,2406 @@
2
+# Doxyfile 1.8.11
3
+
4
+# This file describes the settings to be used by the documentation system
5
+# doxygen (www.doxygen.org) for a project.
6
+#
7
+# All text after a double hash (##) is considered a comment and is placed in
8
+# front of the TAG it is preceding.
9
+#
10
+# All text after a single hash (#) is considered a comment and will be ignored.
11
+# The format is:
12
+# TAG = value [value, ...]
13
+# For lists, items can also be appended using:
14
+# TAG += value [value, ...]
15
+# Values that contain spaces should be placed between quotes (\" \").
16
+
17
+#---------------------------------------------------------------------------
18
+# Project related configuration options
19
+#---------------------------------------------------------------------------
20
+
21
+# This tag specifies the encoding used for all characters in the config file
22
+# that follow. The default is UTF-8 which is also the encoding used for all text
23
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
24
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
25
+# for the list of possible encodings.
26
+# The default value is: UTF-8.
27
+
28
+DOXYFILE_ENCODING      = UTF-8
29
+
30
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
31
+# double-quotes, unless you are using Doxywizard) that should identify the
32
+# project for which the documentation is generated. This name is used in the
33
+# title of most generated pages and in a few other places.
34
+# The default value is: My Project.
35
+
36
+PROJECT_NAME           = "libcaption"
37
+
38
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
39
+# could be handy for archiving the generated documentation or if some version
40
+# control system is used.
41
+
42
+PROJECT_NUMBER         =
43
+
44
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
45
+# for a project that appears at the top of each page and should give viewer a
46
+# quick idea about the purpose of the project. Keep the description short.
47
+
48
+PROJECT_BRIEF          =
49
+
50
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
51
+# in the documentation. The maximum height of the logo should not exceed 55
52
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
53
+# the logo to the output directory.
54
+
55
+PROJECT_LOGO           =
56
+
57
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
58
+# into which the generated documentation will be written. If a relative path is
59
+# entered, it will be relative to the location where doxygen was started. If
60
+# left blank the current directory will be used.
61
+
62
+OUTPUT_DIRECTORY       = ./docs
63
+
64
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
65
+# directories (in 2 levels) under the output directory of each output format and
66
+# will distribute the generated files over these directories. Enabling this
67
+# option can be useful when feeding doxygen a huge amount of source files, where
68
+# putting all generated files in the same directory would otherwise causes
69
+# performance problems for the file system.
70
+# The default value is: NO.
71
+
72
+CREATE_SUBDIRS         = YES
73
+
74
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
75
+# characters to appear in the names of generated files. If set to NO, non-ASCII
76
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
77
+# U+3044.
78
+# The default value is: NO.
79
+
80
+ALLOW_UNICODE_NAMES    = NO
81
+
82
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
83
+# documentation generated by doxygen is written. Doxygen will use this
84
+# information to generate all constant output in the proper language.
85
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
86
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
87
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
88
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
89
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
90
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
91
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
92
+# Ukrainian and Vietnamese.
93
+# The default value is: English.
94
+
95
+OUTPUT_LANGUAGE        = English
96
+
97
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
98
+# descriptions after the members that are listed in the file and class
99
+# documentation (similar to Javadoc). Set to NO to disable this.
100
+# The default value is: YES.
101
+
102
+BRIEF_MEMBER_DESC      = YES
103
+
104
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
105
+# description of a member or function before the detailed description
106
+#
107
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
108
+# brief descriptions will be completely suppressed.
109
+# The default value is: YES.
110
+
111
+REPEAT_BRIEF           = YES
112
+
113
+# This tag implements a quasi-intelligent brief description abbreviator that is
114
+# used to form the text in various listings. Each string in this list, if found
115
+# as the leading text of the brief description, will be stripped from the text
116
+# and the result, after processing the whole list, is used as the annotated
117
+# text. Otherwise, the brief description is used as-is. If left blank, the
118
+# following values are used ($name is automatically replaced with the name of
119
+# the entity):The $name class, The $name widget, The $name file, is, provides,
120
+# specifies, contains, represents, a, an and the.
121
+
122
+ABBREVIATE_BRIEF       =
123
+
124
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
125
+# doxygen will generate a detailed section even if there is only a brief
126
+# description.
127
+# The default value is: NO.
128
+
129
+ALWAYS_DETAILED_SEC    = NO
130
+
131
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
132
+# inherited members of a class in the documentation of that class as if those
133
+# members were ordinary class members. Constructors, destructors and assignment
134
+# operators of the base classes will not be shown.
135
+# The default value is: NO.
136
+
137
+INLINE_INHERITED_MEMB  = NO
138
+
139
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
140
+# before files name in the file list and in the header files. If set to NO the
141
+# shortest path that makes the file name unique will be used
142
+# The default value is: YES.
143
+
144
+FULL_PATH_NAMES        = YES
145
+
146
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
147
+# Stripping is only done if one of the specified strings matches the left-hand
148
+# part of the path. The tag can be used to show relative paths in the file list.
149
+# If left blank the directory from which doxygen is run is used as the path to
150
+# strip.
151
+#
152
+# Note that you can specify absolute paths here, but also relative paths, which
153
+# will be relative from the directory where doxygen is started.
154
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
155
+
156
+STRIP_FROM_PATH        =
157
+
158
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
159
+# path mentioned in the documentation of a class, which tells the reader which
160
+# header file to include in order to use a class. If left blank only the name of
161
+# the header file containing the class definition is used. Otherwise one should
162
+# specify the list of include paths that are normally passed to the compiler
163
+# using the -I flag.
164
+
165
+STRIP_FROM_INC_PATH    =
166
+
167
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
168
+# less readable) file names. This can be useful is your file systems doesn't
169
+# support long names like on DOS, Mac, or CD-ROM.
170
+# The default value is: NO.
171
+
172
+SHORT_NAMES            = NO
173
+
174
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
175
+# first line (until the first dot) of a Javadoc-style comment as the brief
176
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
177
+# style comments (thus requiring an explicit @brief command for a brief
178
+# description.)
179
+# The default value is: NO.
180
+
181
+JAVADOC_AUTOBRIEF      = NO
182
+
183
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
184
+# line (until the first dot) of a Qt-style comment as the brief description. If
185
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
186
+# requiring an explicit \brief command for a brief description.)
187
+# The default value is: NO.
188
+
189
+QT_AUTOBRIEF           = NO
190
+
191
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
192
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
193
+# a brief description. This used to be the default behavior. The new default is
194
+# to treat a multi-line C++ comment block as a detailed description. Set this
195
+# tag to YES if you prefer the old behavior instead.
196
+#
197
+# Note that setting this tag to YES also means that rational rose comments are
198
+# not recognized any more.
199
+# The default value is: NO.
200
+
201
+MULTILINE_CPP_IS_BRIEF = NO
202
+
203
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
204
+# documentation from any documented member that it re-implements.
205
+# The default value is: YES.
206
+
207
+INHERIT_DOCS           = YES
208
+
209
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
210
+# page for each member. If set to NO, the documentation of a member will be part
211
+# of the file/class/namespace that contains it.
212
+# The default value is: NO.
213
+
214
+SEPARATE_MEMBER_PAGES  = NO
215
+
216
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
217
+# uses this value to replace tabs by spaces in code fragments.
218
+# Minimum value: 1, maximum value: 16, default value: 4.
219
+
220
+TAB_SIZE               = 4
221
+
222
+# This tag can be used to specify a number of aliases that act as commands in
223
+# the documentation. An alias has the form:
224
+# name=value
225
+# For example adding
226
+# "sideeffect=@par Side Effects:\n"
227
+# will allow you to put the command \sideeffect (or @sideeffect) in the
228
+# documentation, which will result in a user-defined paragraph with heading
229
+# "Side Effects:". You can put \n's in the value part of an alias to insert
230
+# newlines.
231
+
232
+ALIASES                =
233
+
234
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
235
+# A mapping has the form "name=value". For example adding "class=itcl::class"
236
+# will allow you to use the command class in the itcl::class meaning.
237
+
238
+TCL_SUBST              =
239
+
240
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
241
+# only. Doxygen will then generate output that is more tailored for C. For
242
+# instance, some of the names that are used will be different. The list of all
243
+# members will be omitted, etc.
244
+# The default value is: NO.
245
+
246
+OPTIMIZE_OUTPUT_FOR_C  = NO
247
+
248
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
249
+# Python sources only. Doxygen will then generate output that is more tailored
250
+# for that language. For instance, namespaces will be presented as packages,
251
+# qualified scopes will look different, etc.
252
+# The default value is: NO.
253
+
254
+OPTIMIZE_OUTPUT_JAVA   = NO
255
+
256
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
257
+# sources. Doxygen will then generate output that is tailored for Fortran.
258
+# The default value is: NO.
259
+
260
+OPTIMIZE_FOR_FORTRAN   = NO
261
+
262
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
263
+# sources. Doxygen will then generate output that is tailored for VHDL.
264
+# The default value is: NO.
265
+
266
+OPTIMIZE_OUTPUT_VHDL   = NO
267
+
268
+# Doxygen selects the parser to use depending on the extension of the files it
269
+# parses. With this tag you can assign which parser to use for a given
270
+# extension. Doxygen has a built-in mapping, but you can override or extend it
271
+# using this tag. The format is ext=language, where ext is a file extension, and
272
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
273
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
274
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
275
+# Fortran. In the later case the parser tries to guess whether the code is fixed
276
+# or free formatted code, this is the default for Fortran type files), VHDL. For
277
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
278
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
279
+#
280
+# Note: For files without extension you can use no_extension as a placeholder.
281
+#
282
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
283
+# the files are not read by doxygen.
284
+
285
+EXTENSION_MAPPING      =
286
+
287
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
288
+# according to the Markdown format, which allows for more readable
289
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
290
+# The output of markdown processing is further processed by doxygen, so you can
291
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
292
+# case of backward compatibilities issues.
293
+# The default value is: YES.
294
+
295
+MARKDOWN_SUPPORT       = YES
296
+
297
+# When enabled doxygen tries to link words that correspond to documented
298
+# classes, or namespaces to their corresponding documentation. Such a link can
299
+# be prevented in individual cases by putting a % sign in front of the word or
300
+# globally by setting AUTOLINK_SUPPORT to NO.
301
+# The default value is: YES.
302
+
303
+AUTOLINK_SUPPORT       = YES
304
+
305
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
306
+# to include (a tag file for) the STL sources as input, then you should set this
307
+# tag to YES in order to let doxygen match functions declarations and
308
+# definitions whose arguments contain STL classes (e.g. func(std::string);
309
+# versus func(std::string) {}). This also make the inheritance and collaboration
310
+# diagrams that involve STL classes more complete and accurate.
311
+# The default value is: NO.
312
+
313
+BUILTIN_STL_SUPPORT    = NO
314
+
315
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
316
+# enable parsing support.
317
+# The default value is: NO.
318
+
319
+CPP_CLI_SUPPORT        = NO
320
+
321
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
322
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
323
+# will parse them like normal C++ but will assume all classes use public instead
324
+# of private inheritance when no explicit protection keyword is present.
325
+# The default value is: NO.
326
+
327
+SIP_SUPPORT            = NO
328
+
329
+# For Microsoft's IDL there are propget and propput attributes to indicate
330
+# getter and setter methods for a property. Setting this option to YES will make
331
+# doxygen to replace the get and set methods by a property in the documentation.
332
+# This will only work if the methods are indeed getting or setting a simple
333
+# type. If this is not the case, or you want to show the methods anyway, you
334
+# should set this option to NO.
335
+# The default value is: YES.
336
+
337
+IDL_PROPERTY_SUPPORT   = YES
338
+
339
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
340
+# tag is set to YES then doxygen will reuse the documentation of the first
341
+# member in the group (if any) for the other members of the group. By default
342
+# all members of a group must be documented explicitly.
343
+# The default value is: NO.
344
+
345
+DISTRIBUTE_GROUP_DOC   = NO
346
+
347
+# If one adds a struct or class to a group and this option is enabled, then also
348
+# any nested class or struct is added to the same group. By default this option
349
+# is disabled and one has to add nested compounds explicitly via \ingroup.
350
+# The default value is: NO.
351
+
352
+GROUP_NESTED_COMPOUNDS = NO
353
+
354
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
355
+# (for instance a group of public functions) to be put as a subgroup of that
356
+# type (e.g. under the Public Functions section). Set it to NO to prevent
357
+# subgrouping. Alternatively, this can be done per class using the
358
+# \nosubgrouping command.
359
+# The default value is: YES.
360
+
361
+SUBGROUPING            = YES
362
+
363
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
364
+# are shown inside the group in which they are included (e.g. using \ingroup)
365
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
366
+# and RTF).
367
+#
368
+# Note that this feature does not work in combination with
369
+# SEPARATE_MEMBER_PAGES.
370
+# The default value is: NO.
371
+
372
+INLINE_GROUPED_CLASSES = NO
373
+
374
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
375
+# with only public data fields or simple typedef fields will be shown inline in
376
+# the documentation of the scope in which they are defined (i.e. file,
377
+# namespace, or group documentation), provided this scope is documented. If set
378
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
379
+# Man pages) or section (for LaTeX and RTF).
380
+# The default value is: NO.
381
+
382
+INLINE_SIMPLE_STRUCTS  = NO
383
+
384
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
385
+# enum is documented as struct, union, or enum with the name of the typedef. So
386
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
387
+# with name TypeT. When disabled the typedef will appear as a member of a file,
388
+# namespace, or class. And the struct will be named TypeS. This can typically be
389
+# useful for C code in case the coding convention dictates that all compound
390
+# types are typedef'ed and only the typedef is referenced, never the tag name.
391
+# The default value is: NO.
392
+
393
+TYPEDEF_HIDES_STRUCT   = NO
394
+
395
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
396
+# cache is used to resolve symbols given their name and scope. Since this can be
397
+# an expensive process and often the same symbol appears multiple times in the
398
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
399
+# doxygen will become slower. If the cache is too large, memory is wasted. The
400
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
401
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
402
+# symbols. At the end of a run doxygen will report the cache usage and suggest
403
+# the optimal cache size from a speed point of view.
404
+# Minimum value: 0, maximum value: 9, default value: 0.
405
+
406
+LOOKUP_CACHE_SIZE      = 0
407
+
408
+#---------------------------------------------------------------------------
409
+# Build related configuration options
410
+#---------------------------------------------------------------------------
411
+
412
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
413
+# documentation are documented, even if no documentation was available. Private
414
+# class members and static file members will be hidden unless the
415
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
416
+# Note: This will also disable the warnings about undocumented members that are
417
+# normally produced when WARNINGS is set to YES.
418
+# The default value is: NO.
419
+
420
+EXTRACT_ALL            = YES
421
+
422
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
423
+# be included in the documentation.
424
+# The default value is: NO.
425
+
426
+EXTRACT_PRIVATE        = NO
427
+
428
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
429
+# scope will be included in the documentation.
430
+# The default value is: NO.
431
+
432
+EXTRACT_PACKAGE        = NO
433
+
434
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
435
+# included in the documentation.
436
+# The default value is: NO.
437
+
438
+EXTRACT_STATIC         = YES
439
+
440
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
441
+# locally in source files will be included in the documentation. If set to NO,
442
+# only classes defined in header files are included. Does not have any effect
443
+# for Java sources.
444
+# The default value is: YES.
445
+
446
+EXTRACT_LOCAL_CLASSES  = YES
447
+
448
+# This flag is only useful for Objective-C code. If set to YES, local methods,
449
+# which are defined in the implementation section but not in the interface are
450
+# included in the documentation. If set to NO, only methods in the interface are
451
+# included.
452
+# The default value is: NO.
453
+
454
+EXTRACT_LOCAL_METHODS  = NO
455
+
456
+# If this flag is set to YES, the members of anonymous namespaces will be
457
+# extracted and appear in the documentation as a namespace called
458
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
459
+# the file that contains the anonymous namespace. By default anonymous namespace
460
+# are hidden.
461
+# The default value is: NO.
462
+
463
+EXTRACT_ANON_NSPACES   = NO
464
+
465
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
466
+# undocumented members inside documented classes or files. If set to NO these
467
+# members will be included in the various overviews, but no documentation
468
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
469
+# The default value is: NO.
470
+
471
+HIDE_UNDOC_MEMBERS     = NO
472
+
473
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
474
+# undocumented classes that are normally visible in the class hierarchy. If set
475
+# to NO, these classes will be included in the various overviews. This option
476
+# has no effect if EXTRACT_ALL is enabled.
477
+# The default value is: NO.
478
+
479
+HIDE_UNDOC_CLASSES     = NO
480
+
481
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
482
+# (class|struct|union) declarations. If set to NO, these declarations will be
483
+# included in the documentation.
484
+# The default value is: NO.
485
+
486
+HIDE_FRIEND_COMPOUNDS  = NO
487
+
488
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
489
+# documentation blocks found inside the body of a function. If set to NO, these
490
+# blocks will be appended to the function's detailed documentation block.
491
+# The default value is: NO.
492
+
493
+HIDE_IN_BODY_DOCS      = NO
494
+
495
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
496
+# \internal command is included. If the tag is set to NO then the documentation
497
+# will be excluded. Set it to YES to include the internal documentation.
498
+# The default value is: NO.
499
+
500
+INTERNAL_DOCS          = NO
501
+
502
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
503
+# names in lower-case letters. If set to YES, upper-case letters are also
504
+# allowed. This is useful if you have classes or files whose names only differ
505
+# in case and if your file system supports case sensitive file names. Windows
506
+# and Mac users are advised to set this option to NO.
507
+# The default value is: system dependent.
508
+
509
+CASE_SENSE_NAMES       = NO
510
+
511
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
512
+# their full class and namespace scopes in the documentation. If set to YES, the
513
+# scope will be hidden.
514
+# The default value is: NO.
515
+
516
+HIDE_SCOPE_NAMES       = NO
517
+
518
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
519
+# append additional text to a page's title, such as Class Reference. If set to
520
+# YES the compound reference will be hidden.
521
+# The default value is: NO.
522
+
523
+HIDE_COMPOUND_REFERENCE= NO
524
+
525
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
526
+# the files that are included by a file in the documentation of that file.
527
+# The default value is: YES.
528
+
529
+SHOW_INCLUDE_FILES     = YES
530
+
531
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
532
+# grouped member an include statement to the documentation, telling the reader
533
+# which file to include in order to use the member.
534
+# The default value is: NO.
535
+
536
+SHOW_GROUPED_MEMB_INC  = NO
537
+
538
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
539
+# files with double quotes in the documentation rather than with sharp brackets.
540
+# The default value is: NO.
541
+
542
+FORCE_LOCAL_INCLUDES   = NO
543
+
544
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
545
+# documentation for inline members.
546
+# The default value is: YES.
547
+
548
+INLINE_INFO            = YES
549
+
550
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
551
+# (detailed) documentation of file and class members alphabetically by member
552
+# name. If set to NO, the members will appear in declaration order.
553
+# The default value is: YES.
554
+
555
+SORT_MEMBER_DOCS       = YES
556
+
557
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
558
+# descriptions of file, namespace and class members alphabetically by member
559
+# name. If set to NO, the members will appear in declaration order. Note that
560
+# this will also influence the order of the classes in the class list.
561
+# The default value is: NO.
562
+
563
+SORT_BRIEF_DOCS        = NO
564
+
565
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
566
+# (brief and detailed) documentation of class members so that constructors and
567
+# destructors are listed first. If set to NO the constructors will appear in the
568
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
569
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
570
+# member documentation.
571
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
572
+# detailed member documentation.
573
+# The default value is: NO.
574
+
575
+SORT_MEMBERS_CTORS_1ST = NO
576
+
577
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
578
+# of group names into alphabetical order. If set to NO the group names will
579
+# appear in their defined order.
580
+# The default value is: NO.
581
+
582
+SORT_GROUP_NAMES       = NO
583
+
584
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
585
+# fully-qualified names, including namespaces. If set to NO, the class list will
586
+# be sorted only by class name, not including the namespace part.
587
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
588
+# Note: This option applies only to the class list, not to the alphabetical
589
+# list.
590
+# The default value is: NO.
591
+
592
+SORT_BY_SCOPE_NAME     = NO
593
+
594
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
595
+# type resolution of all parameters of a function it will reject a match between
596
+# the prototype and the implementation of a member function even if there is
597
+# only one candidate or it is obvious which candidate to choose by doing a
598
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
599
+# accept a match between prototype and implementation in such cases.
600
+# The default value is: NO.
601
+
602
+STRICT_PROTO_MATCHING  = NO
603
+
604
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
605
+# list. This list is created by putting \todo commands in the documentation.
606
+# The default value is: YES.
607
+
608
+GENERATE_TODOLIST      = YES
609
+
610
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
611
+# list. This list is created by putting \test commands in the documentation.
612
+# The default value is: YES.
613
+
614
+GENERATE_TESTLIST      = YES
615
+
616
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
617
+# list. This list is created by putting \bug commands in the documentation.
618
+# The default value is: YES.
619
+
620
+GENERATE_BUGLIST       = YES
621
+
622
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
623
+# the deprecated list. This list is created by putting \deprecated commands in
624
+# the documentation.
625
+# The default value is: YES.
626
+
627
+GENERATE_DEPRECATEDLIST= YES
628
+
629
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
630
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
631
+# ... \endcond blocks.
632
+
633
+ENABLED_SECTIONS       =
634
+
635
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
636
+# initial value of a variable or macro / define can have for it to appear in the
637
+# documentation. If the initializer consists of more lines than specified here
638
+# it will be hidden. Use a value of 0 to hide initializers completely. The
639
+# appearance of the value of individual variables and macros / defines can be
640
+# controlled using \showinitializer or \hideinitializer command in the
641
+# documentation regardless of this setting.
642
+# Minimum value: 0, maximum value: 10000, default value: 30.
643
+
644
+MAX_INITIALIZER_LINES  = 30
645
+
646
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
647
+# the bottom of the documentation of classes and structs. If set to YES, the
648
+# list will mention the files that were used to generate the documentation.
649
+# The default value is: YES.
650
+
651
+SHOW_USED_FILES        = YES
652
+
653
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
654
+# will remove the Files entry from the Quick Index and from the Folder Tree View
655
+# (if specified).
656
+# The default value is: YES.
657
+
658
+SHOW_FILES             = YES
659
+
660
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
661
+# page. This will remove the Namespaces entry from the Quick Index and from the
662
+# Folder Tree View (if specified).
663
+# The default value is: YES.
664
+
665
+SHOW_NAMESPACES        = YES
666
+
667
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
668
+# doxygen should invoke to get the current version for each file (typically from
669
+# the version control system). Doxygen will invoke the program by executing (via
670
+# popen()) the command command input-file, where command is the value of the
671
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
672
+# by doxygen. Whatever the program writes to standard output is used as the file
673
+# version. For an example see the documentation.
674
+
675
+FILE_VERSION_FILTER    =
676
+
677
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
678
+# by doxygen. The layout file controls the global structure of the generated
679
+# output files in an output format independent way. To create the layout file
680
+# that represents doxygen's defaults, run doxygen with the -l option. You can
681
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
682
+# will be used as the name of the layout file.
683
+#
684
+# Note that if you run doxygen from a directory containing a file called
685
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
686
+# tag is left empty.
687
+
688
+LAYOUT_FILE            =
689
+
690
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
691
+# the reference definitions. This must be a list of .bib files. The .bib
692
+# extension is automatically appended if omitted. This requires the bibtex tool
693
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
694
+# For LaTeX the style of the bibliography can be controlled using
695
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
696
+# search path. See also \cite for info how to create references.
697
+
698
+CITE_BIB_FILES         =
699
+
700
+#---------------------------------------------------------------------------
701
+# Configuration options related to warning and progress messages
702
+#---------------------------------------------------------------------------
703
+
704
+# The QUIET tag can be used to turn on/off the messages that are generated to
705
+# standard output by doxygen. If QUIET is set to YES this implies that the
706
+# messages are off.
707
+# The default value is: NO.
708
+
709
+QUIET                  = NO
710
+
711
+# The WARNINGS tag can be used to turn on/off the warning messages that are
712
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
713
+# this implies that the warnings are on.
714
+#
715
+# Tip: Turn warnings on while writing the documentation.
716
+# The default value is: YES.
717
+
718
+WARNINGS               = YES
719
+
720
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
721
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
722
+# will automatically be disabled.
723
+# The default value is: YES.
724
+
725
+WARN_IF_UNDOCUMENTED   = YES
726
+
727
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
728
+# potential errors in the documentation, such as not documenting some parameters
729
+# in a documented function, or documenting parameters that don't exist or using
730
+# markup commands wrongly.
731
+# The default value is: YES.
732
+
733
+WARN_IF_DOC_ERROR      = YES
734
+
735
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
736
+# are documented, but have no documentation for their parameters or return
737
+# value. If set to NO, doxygen will only warn about wrong or incomplete
738
+# parameter documentation, but not about the absence of documentation.
739
+# The default value is: NO.
740
+
741
+WARN_NO_PARAMDOC       = NO
742
+
743
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
744
+# a warning is encountered.
745
+# The default value is: NO.
746
+
747
+WARN_AS_ERROR          = NO
748
+
749
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
750
+# can produce. The string should contain the $file, $line, and $text tags, which
751
+# will be replaced by the file and line number from which the warning originated
752
+# and the warning text. Optionally the format may contain $version, which will
753
+# be replaced by the version of the file (if it could be obtained via
754
+# FILE_VERSION_FILTER)
755
+# The default value is: $file:$line: $text.
756
+
757
+WARN_FORMAT            = "$file:$line: $text"
758
+
759
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
760
+# messages should be written. If left blank the output is written to standard
761
+# error (stderr).
762
+
763
+WARN_LOGFILE           =
764
+
765
+#---------------------------------------------------------------------------
766
+# Configuration options related to the input files
767
+#---------------------------------------------------------------------------
768
+
769
+# The INPUT tag is used to specify the files and/or directories that contain
770
+# documented source files. You may enter file names like myfile.cpp or
771
+# directories like /usr/src/myproject. Separate the files or directories with
772
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
773
+# Note: If this tag is empty the current directory is searched.
774
+
775
+INPUT                  = @CMAKE_CURRENT_SOURCE_DIR@/include @CMAKE_CURRENT_SOURCE_DIR@/examples
776
+
777
+# This tag can be used to specify the character encoding of the source files
778
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
779
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
780
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
781
+# possible encodings.
782
+# The default value is: UTF-8.
783
+
784
+INPUT_ENCODING         = UTF-8
785
+
786
+# If the value of the INPUT tag contains directories, you can use the
787
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
788
+# *.h) to filter out the source-files in the directories.
789
+#
790
+# Note that for custom extensions or not directly supported extensions you also
791
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
792
+# read by doxygen.
793
+#
794
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
795
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
796
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
797
+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl,
798
+# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js.
799
+
800
+FILE_PATTERNS          = *.h *.c *.re2c
801
+
802
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
803
+# be searched for input files as well.
804
+# The default value is: NO.
805
+
806
+RECURSIVE              = YES
807
+
808
+# The EXCLUDE tag can be used to specify files and/or directories that should be
809
+# excluded from the INPUT source files. This way you can easily exclude a
810
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
811
+#
812
+# Note that relative paths are relative to the directory from which doxygen is
813
+# run.
814
+
815
+EXCLUDE                =
816
+
817
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
818
+# directories that are symbolic links (a Unix file system feature) are excluded
819
+# from the input.
820
+# The default value is: NO.
821
+
822
+EXCLUDE_SYMLINKS       = NO
823
+
824
+# If the value of the INPUT tag contains directories, you can use the
825
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
826
+# certain files from those directories.
827
+#
828
+# Note that the wildcards are matched against the file with absolute path, so to
829
+# exclude all test directories for example use the pattern */test/*
830
+
831
+EXCLUDE_PATTERNS       =
832
+
833
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
834
+# (namespaces, classes, functions, etc.) that should be excluded from the
835
+# output. The symbol name can be a fully qualified name, a word, or if the
836
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
837
+# AClass::ANamespace, ANamespace::*Test
838
+#
839
+# Note that the wildcards are matched against the file with absolute path, so to
840
+# exclude all test directories use the pattern */test/*
841
+
842
+EXCLUDE_SYMBOLS        =
843
+
844
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
845
+# that contain example code fragments that are included (see the \include
846
+# command).
847
+
848
+EXAMPLE_PATH           =
849
+
850
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
851
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
852
+# *.h) to filter out the source-files in the directories. If left blank all
853
+# files are included.
854
+
855
+EXAMPLE_PATTERNS       =
856
+
857
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
858
+# searched for input files to be used with the \include or \dontinclude commands
859
+# irrespective of the value of the RECURSIVE tag.
860
+# The default value is: NO.
861
+
862
+EXAMPLE_RECURSIVE      = NO
863
+
864
+# The IMAGE_PATH tag can be used to specify one or more files or directories
865
+# that contain images that are to be included in the documentation (see the
866
+# \image command).
867
+
868
+IMAGE_PATH             =
869
+
870
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
871
+# invoke to filter for each input file. Doxygen will invoke the filter program
872
+# by executing (via popen()) the command:
873
+#
874
+# <filter> <input-file>
875
+#
876
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
877
+# name of an input file. Doxygen will then use the output that the filter
878
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
879
+# will be ignored.
880
+#
881
+# Note that the filter must not add or remove lines; it is applied before the
882
+# code is scanned, but not when the output code is generated. If lines are added
883
+# or removed, the anchors will not be placed correctly.
884
+#
885
+# Note that for custom extensions or not directly supported extensions you also
886
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
887
+# properly processed by doxygen.
888
+
889
+INPUT_FILTER           =
890
+
891
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
892
+# basis. Doxygen will compare the file name with each pattern and apply the
893
+# filter if there is a match. The filters are a list of the form: pattern=filter
894
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
895
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
896
+# patterns match the file name, INPUT_FILTER is applied.
897
+#
898
+# Note that for custom extensions or not directly supported extensions you also
899
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
900
+# properly processed by doxygen.
901
+
902
+FILTER_PATTERNS        =
903
+
904
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
905
+# INPUT_FILTER) will also be used to filter the input files that are used for
906
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
907
+# The default value is: NO.
908
+
909
+FILTER_SOURCE_FILES    = NO
910
+
911
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
912
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
913
+# it is also possible to disable source filtering for a specific pattern using
914
+# *.ext= (so without naming a filter).
915
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
916
+
917
+FILTER_SOURCE_PATTERNS =
918
+
919
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
920
+# is part of the input, its contents will be placed on the main page
921
+# (index.html). This can be useful if you have a project on for instance GitHub
922
+# and want to reuse the introduction page also for the doxygen output.
923
+
924
+USE_MDFILE_AS_MAINPAGE =
925
+
926
+#---------------------------------------------------------------------------
927
+# Configuration options related to source browsing
928
+#---------------------------------------------------------------------------
929
+
930
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
931
+# generated. Documented entities will be cross-referenced with these sources.
932
+#
933
+# Note: To get rid of all source code in the generated output, make sure that
934
+# also VERBATIM_HEADERS is set to NO.
935
+# The default value is: NO.
936
+
937
+SOURCE_BROWSER         = NO
938
+
939
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
940
+# classes and enums directly into the documentation.
941
+# The default value is: NO.
942
+
943
+INLINE_SOURCES         = NO
944
+
945
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
946
+# special comment blocks from generated source code fragments. Normal C, C++ and
947
+# Fortran comments will always remain visible.
948
+# The default value is: YES.
949
+
950
+STRIP_CODE_COMMENTS    = YES
951
+
952
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
953
+# function all documented functions referencing it will be listed.
954
+# The default value is: NO.
955
+
956
+REFERENCED_BY_RELATION = NO
957
+
958
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
959
+# all documented entities called/used by that function will be listed.
960
+# The default value is: NO.
961
+
962
+REFERENCES_RELATION    = NO
963
+
964
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
965
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
966
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
967
+# link to the documentation.
968
+# The default value is: YES.
969
+
970
+REFERENCES_LINK_SOURCE = YES
971
+
972
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
973
+# source code will show a tooltip with additional information such as prototype,
974
+# brief description and links to the definition and documentation. Since this
975
+# will make the HTML file larger and loading of large files a bit slower, you
976
+# can opt to disable this feature.
977
+# The default value is: YES.
978
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
979
+
980
+SOURCE_TOOLTIPS        = YES
981
+
982
+# If the USE_HTAGS tag is set to YES then the references to source code will
983
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
984
+# source browser. The htags tool is part of GNU's global source tagging system
985
+# (see http://www.gnu.org/software/global/global.html). You will need version
986
+# 4.8.6 or higher.
987
+#
988
+# To use it do the following:
989
+# - Install the latest version of global
990
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
991
+# - Make sure the INPUT points to the root of the source tree
992
+# - Run doxygen as normal
993
+#
994
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
995
+# tools must be available from the command line (i.e. in the search path).
996
+#
997
+# The result: instead of the source browser generated by doxygen, the links to
998
+# source code will now point to the output of htags.
999
+# The default value is: NO.
1000
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
1001
+
1002
+USE_HTAGS              = NO
1003
+
1004
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
1005
+# verbatim copy of the header file for each class for which an include is
1006
+# specified. Set to NO to disable this.
1007
+# See also: Section \class.
1008
+# The default value is: YES.
1009
+
1010
+VERBATIM_HEADERS       = YES
1011
+
1012
+#---------------------------------------------------------------------------
1013
+# Configuration options related to the alphabetical class index
1014
+#---------------------------------------------------------------------------
1015
+
1016
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
1017
+# compounds will be generated. Enable this if the project contains a lot of
1018
+# classes, structs, unions or interfaces.
1019
+# The default value is: YES.
1020
+
1021
+ALPHABETICAL_INDEX     = YES
1022
+
1023
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
1024
+# which the alphabetical index list will be split.
1025
+# Minimum value: 1, maximum value: 20, default value: 5.
1026
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
1027
+
1028
+COLS_IN_ALPHA_INDEX    = 5
1029
+
1030
+# In case all classes in a project start with a common prefix, all classes will
1031
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
1032
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
1033
+# while generating the index headers.
1034
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
1035
+
1036
+IGNORE_PREFIX          =
1037
+
1038
+#---------------------------------------------------------------------------
1039
+# Configuration options related to the HTML output
1040
+#---------------------------------------------------------------------------
1041
+
1042
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
1043
+# The default value is: YES.
1044
+
1045
+GENERATE_HTML          = YES
1046
+
1047
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
1048
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1049
+# it.
1050
+# The default directory is: html.
1051
+# This tag requires that the tag GENERATE_HTML is set to YES.
1052
+
1053
+HTML_OUTPUT            = html
1054
+
1055
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
1056
+# generated HTML page (for example: .htm, .php, .asp).
1057
+# The default value is: .html.
1058
+# This tag requires that the tag GENERATE_HTML is set to YES.
1059
+
1060
+HTML_FILE_EXTENSION    = .html
1061
+
1062
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
1063
+# each generated HTML page. If the tag is left blank doxygen will generate a
1064
+# standard header.
1065
+#
1066
+# To get valid HTML the header file that includes any scripts and style sheets
1067
+# that doxygen needs, which is dependent on the configuration options used (e.g.
1068
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
1069
+# default header using
1070
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
1071
+# YourConfigFile
1072
+# and then modify the file new_header.html. See also section "Doxygen usage"
1073
+# for information on how to generate the default header that doxygen normally
1074
+# uses.
1075
+# Note: The header is subject to change so you typically have to regenerate the
1076
+# default header when upgrading to a newer version of doxygen. For a description
1077
+# of the possible markers and block names see the documentation.
1078
+# This tag requires that the tag GENERATE_HTML is set to YES.
1079
+
1080
+HTML_HEADER            =
1081
+
1082
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
1083
+# generated HTML page. If the tag is left blank doxygen will generate a standard
1084
+# footer. See HTML_HEADER for more information on how to generate a default
1085
+# footer and what special commands can be used inside the footer. See also
1086
+# section "Doxygen usage" for information on how to generate the default footer
1087
+# that doxygen normally uses.
1088
+# This tag requires that the tag GENERATE_HTML is set to YES.
1089
+
1090
+HTML_FOOTER            =
1091
+
1092
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
1093
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
1094
+# the HTML output. If left blank doxygen will generate a default style sheet.
1095
+# See also section "Doxygen usage" for information on how to generate the style
1096
+# sheet that doxygen normally uses.
1097
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
1098
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
1099
+# obsolete.
1100
+# This tag requires that the tag GENERATE_HTML is set to YES.
1101
+
1102
+HTML_STYLESHEET        =
1103
+
1104
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
1105
+# cascading style sheets that are included after the standard style sheets
1106
+# created by doxygen. Using this option one can overrule certain style aspects.
1107
+# This is preferred over using HTML_STYLESHEET since it does not replace the
1108
+# standard style sheet and is therefore more robust against future updates.
1109
+# Doxygen will copy the style sheet files to the output directory.
1110
+# Note: The order of the extra style sheet files is of importance (e.g. the last
1111
+# style sheet in the list overrules the setting of the previous ones in the
1112
+# list). For an example see the documentation.
1113
+# This tag requires that the tag GENERATE_HTML is set to YES.
1114
+
1115
+HTML_EXTRA_STYLESHEET  =
1116
+
1117
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
1118
+# other source files which should be copied to the HTML output directory. Note
1119
+# that these files will be copied to the base HTML output directory. Use the
1120
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
1121
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
1122
+# files will be copied as-is; there are no commands or markers available.
1123
+# This tag requires that the tag GENERATE_HTML is set to YES.
1124
+
1125
+HTML_EXTRA_FILES       =
1126
+
1127
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
1128
+# will adjust the colors in the style sheet and background images according to
1129
+# this color. Hue is specified as an angle on a colorwheel, see
1130
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
1131
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
1132
+# purple, and 360 is red again.
1133
+# Minimum value: 0, maximum value: 359, default value: 220.
1134
+# This tag requires that the tag GENERATE_HTML is set to YES.
1135
+
1136
+HTML_COLORSTYLE_HUE    = 220
1137
+
1138
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
1139
+# in the HTML output. For a value of 0 the output will use grayscales only. A
1140
+# value of 255 will produce the most vivid colors.
1141
+# Minimum value: 0, maximum value: 255, default value: 100.
1142
+# This tag requires that the tag GENERATE_HTML is set to YES.
1143
+
1144
+HTML_COLORSTYLE_SAT    = 100
1145
+
1146
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
1147
+# luminance component of the colors in the HTML output. Values below 100
1148
+# gradually make the output lighter, whereas values above 100 make the output
1149
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
1150
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
1151
+# change the gamma.
1152
+# Minimum value: 40, maximum value: 240, default value: 80.
1153
+# This tag requires that the tag GENERATE_HTML is set to YES.
1154
+
1155
+HTML_COLORSTYLE_GAMMA  = 80
1156
+
1157
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
1158
+# page will contain the date and time when the page was generated. Setting this
1159
+# to YES can help to show when doxygen was last run and thus if the
1160
+# documentation is up to date.
1161
+# The default value is: NO.
1162
+# This tag requires that the tag GENERATE_HTML is set to YES.
1163
+
1164
+HTML_TIMESTAMP         = NO
1165
+
1166
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
1167
+# documentation will contain sections that can be hidden and shown after the
1168
+# page has loaded.
1169
+# The default value is: NO.
1170
+# This tag requires that the tag GENERATE_HTML is set to YES.
1171
+
1172
+HTML_DYNAMIC_SECTIONS  = NO
1173
+
1174
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
1175
+# shown in the various tree structured indices initially; the user can expand
1176
+# and collapse entries dynamically later on. Doxygen will expand the tree to
1177
+# such a level that at most the specified number of entries are visible (unless
1178
+# a fully collapsed tree already exceeds this amount). So setting the number of
1179
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
1180
+# representing an infinite number of entries and will result in a full expanded
1181
+# tree by default.
1182
+# Minimum value: 0, maximum value: 9999, default value: 100.
1183
+# This tag requires that the tag GENERATE_HTML is set to YES.
1184
+
1185
+HTML_INDEX_NUM_ENTRIES = 100
1186
+
1187
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
1188
+# generated that can be used as input for Apple's Xcode 3 integrated development
1189
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
1190
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
1191
+# Makefile in the HTML output directory. Running make will produce the docset in
1192
+# that directory and running make install will install the docset in
1193
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
1194
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
1195
+# for more information.
1196
+# The default value is: NO.
1197
+# This tag requires that the tag GENERATE_HTML is set to YES.
1198
+
1199
+GENERATE_DOCSET        = NO
1200
+
1201
+# This tag determines the name of the docset feed. A documentation feed provides
1202
+# an umbrella under which multiple documentation sets from a single provider
1203
+# (such as a company or product suite) can be grouped.
1204
+# The default value is: Doxygen generated docs.
1205
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
1206
+
1207
+DOCSET_FEEDNAME        = "Doxygen generated docs"
1208
+
1209
+# This tag specifies a string that should uniquely identify the documentation
1210
+# set bundle. This should be a reverse domain-name style string, e.g.
1211
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
1212
+# The default value is: org.doxygen.Project.
1213
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
1214
+
1215
+DOCSET_BUNDLE_ID       = org.doxygen.Project
1216
+
1217
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
1218
+# the documentation publisher. This should be a reverse domain-name style
1219
+# string, e.g. com.mycompany.MyDocSet.documentation.
1220
+# The default value is: org.doxygen.Publisher.
1221
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
1222
+
1223
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
1224
+
1225
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
1226
+# The default value is: Publisher.
1227
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
1228
+
1229
+DOCSET_PUBLISHER_NAME  = Publisher
1230
+
1231
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
1232
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
1233
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
1234
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
1235
+# Windows.
1236
+#
1237
+# The HTML Help Workshop contains a compiler that can convert all HTML output
1238
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
1239
+# files are now used as the Windows 98 help format, and will replace the old
1240
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
1241
+# HTML files also contain an index, a table of contents, and you can search for
1242
+# words in the documentation. The HTML workshop also contains a viewer for
1243
+# compressed HTML files.
1244
+# The default value is: NO.
1245
+# This tag requires that the tag GENERATE_HTML is set to YES.
1246
+
1247
+GENERATE_HTMLHELP      = NO
1248
+
1249
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
1250
+# file. You can add a path in front of the file if the result should not be
1251
+# written to the html output directory.
1252
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1253
+
1254
+CHM_FILE               =
1255
+
1256
+# The HHC_LOCATION tag can be used to specify the location (absolute path
1257
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
1258
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
1259
+# The file has to be specified with full path.
1260
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1261
+
1262
+HHC_LOCATION           =
1263
+
1264
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
1265
+# (YES) or that it should be included in the master .chm file (NO).
1266
+# The default value is: NO.
1267
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1268
+
1269
+GENERATE_CHI           = NO
1270
+
1271
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
1272
+# and project file content.
1273
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1274
+
1275
+CHM_INDEX_ENCODING     =
1276
+
1277
+# The BINARY_TOC flag controls whether a binary table of contents is generated
1278
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
1279
+# enables the Previous and Next buttons.
1280
+# The default value is: NO.
1281
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1282
+
1283
+BINARY_TOC             = NO
1284
+
1285
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
1286
+# the table of contents of the HTML help documentation and to the tree view.
1287
+# The default value is: NO.
1288
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1289
+
1290
+TOC_EXPAND             = NO
1291
+
1292
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
1293
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
1294
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
1295
+# (.qch) of the generated HTML documentation.
1296
+# The default value is: NO.
1297
+# This tag requires that the tag GENERATE_HTML is set to YES.
1298
+
1299
+GENERATE_QHP           = NO
1300
+
1301
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
1302
+# the file name of the resulting .qch file. The path specified is relative to
1303
+# the HTML output folder.
1304
+# This tag requires that the tag GENERATE_QHP is set to YES.
1305
+
1306
+QCH_FILE               =
1307
+
1308
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
1309
+# Project output. For more information please see Qt Help Project / Namespace
1310
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
1311
+# The default value is: org.doxygen.Project.
1312
+# This tag requires that the tag GENERATE_QHP is set to YES.
1313
+
1314
+QHP_NAMESPACE          = org.doxygen.Project
1315
+
1316
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
1317
+# Help Project output. For more information please see Qt Help Project / Virtual
1318
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
1319
+# folders).
1320
+# The default value is: doc.
1321
+# This tag requires that the tag GENERATE_QHP is set to YES.
1322
+
1323
+QHP_VIRTUAL_FOLDER     = doc
1324
+
1325
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
1326
+# filter to add. For more information please see Qt Help Project / Custom
1327
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
1328
+# filters).
1329
+# This tag requires that the tag GENERATE_QHP is set to YES.
1330
+
1331
+QHP_CUST_FILTER_NAME   =
1332
+
1333
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
1334
+# custom filter to add. For more information please see Qt Help Project / Custom
1335
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
1336
+# filters).
1337
+# This tag requires that the tag GENERATE_QHP is set to YES.
1338
+
1339
+QHP_CUST_FILTER_ATTRS  =
1340
+
1341
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
1342
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
1343
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
1344
+# This tag requires that the tag GENERATE_QHP is set to YES.
1345
+
1346
+QHP_SECT_FILTER_ATTRS  =
1347
+
1348
+# The QHG_LOCATION tag can be used to specify the location of Qt's
1349
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
1350
+# generated .qhp file.
1351
+# This tag requires that the tag GENERATE_QHP is set to YES.
1352
+
1353
+QHG_LOCATION           =
1354
+
1355
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
1356
+# generated, together with the HTML files, they form an Eclipse help plugin. To
1357
+# install this plugin and make it available under the help contents menu in
1358
+# Eclipse, the contents of the directory containing the HTML and XML files needs
1359
+# to be copied into the plugins directory of eclipse. The name of the directory
1360
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
1361
+# After copying Eclipse needs to be restarted before the help appears.
1362
+# The default value is: NO.
1363
+# This tag requires that the tag GENERATE_HTML is set to YES.
1364
+
1365
+GENERATE_ECLIPSEHELP   = NO
1366
+
1367
+# A unique identifier for the Eclipse help plugin. When installing the plugin
1368
+# the directory name containing the HTML and XML files should also have this
1369
+# name. Each documentation set should have its own identifier.
1370
+# The default value is: org.doxygen.Project.
1371
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
1372
+
1373
+ECLIPSE_DOC_ID         = org.doxygen.Project
1374
+
1375
+# If you want full control over the layout of the generated HTML pages it might
1376
+# be necessary to disable the index and replace it with your own. The
1377
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
1378
+# of each HTML page. A value of NO enables the index and the value YES disables
1379
+# it. Since the tabs in the index contain the same information as the navigation
1380
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
1381
+# The default value is: NO.
1382
+# This tag requires that the tag GENERATE_HTML is set to YES.
1383
+
1384
+DISABLE_INDEX          = NO
1385
+
1386
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
1387
+# structure should be generated to display hierarchical information. If the tag
1388
+# value is set to YES, a side panel will be generated containing a tree-like
1389
+# index structure (just like the one that is generated for HTML Help). For this
1390
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
1391
+# (i.e. any modern browser). Windows users are probably better off using the
1392
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
1393
+# further fine-tune the look of the index. As an example, the default style
1394
+# sheet generated by doxygen has an example that shows how to put an image at
1395
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
1396
+# the same information as the tab index, you could consider setting
1397
+# DISABLE_INDEX to YES when enabling this option.
1398
+# The default value is: NO.
1399
+# This tag requires that the tag GENERATE_HTML is set to YES.
1400
+
1401
+GENERATE_TREEVIEW      = NO
1402
+
1403
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
1404
+# doxygen will group on one line in the generated HTML documentation.
1405
+#
1406
+# Note that a value of 0 will completely suppress the enum values from appearing
1407
+# in the overview section.
1408
+# Minimum value: 0, maximum value: 20, default value: 4.
1409
+# This tag requires that the tag GENERATE_HTML is set to YES.
1410
+
1411
+ENUM_VALUES_PER_LINE   = 4
1412
+
1413
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
1414
+# to set the initial width (in pixels) of the frame in which the tree is shown.
1415
+# Minimum value: 0, maximum value: 1500, default value: 250.
1416
+# This tag requires that the tag GENERATE_HTML is set to YES.
1417
+
1418
+TREEVIEW_WIDTH         = 250
1419
+
1420
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
1421
+# external symbols imported via tag files in a separate window.
1422
+# The default value is: NO.
1423
+# This tag requires that the tag GENERATE_HTML is set to YES.
1424
+
1425
+EXT_LINKS_IN_WINDOW    = NO
1426
+
1427
+# Use this tag to change the font size of LaTeX formulas included as images in
1428
+# the HTML documentation. When you change the font size after a successful
1429
+# doxygen run you need to manually remove any form_*.png images from the HTML
1430
+# output directory to force them to be regenerated.
1431
+# Minimum value: 8, maximum value: 50, default value: 10.
1432
+# This tag requires that the tag GENERATE_HTML is set to YES.
1433
+
1434
+FORMULA_FONTSIZE       = 10
1435
+
1436
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
1437
+# generated for formulas are transparent PNGs. Transparent PNGs are not
1438
+# supported properly for IE 6.0, but are supported on all modern browsers.
1439
+#
1440
+# Note that when changing this option you need to delete any form_*.png files in
1441
+# the HTML output directory before the changes have effect.
1442
+# The default value is: YES.
1443
+# This tag requires that the tag GENERATE_HTML is set to YES.
1444
+
1445
+FORMULA_TRANSPARENT    = YES
1446
+
1447
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
1448
+# http://www.mathjax.org) which uses client side Javascript for the rendering
1449
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
1450
+# installed or if you want to formulas look prettier in the HTML output. When
1451
+# enabled you may also need to install MathJax separately and configure the path
1452
+# to it using the MATHJAX_RELPATH option.
1453
+# The default value is: NO.
1454
+# This tag requires that the tag GENERATE_HTML is set to YES.
1455
+
1456
+USE_MATHJAX            = NO
1457
+
1458
+# When MathJax is enabled you can set the default output format to be used for
1459
+# the MathJax output. See the MathJax site (see:
1460
+# http://docs.mathjax.org/en/latest/output.html) for more details.
1461
+# Possible values are: HTML-CSS (which is slower, but has the best
1462
+# compatibility), NativeMML (i.e. MathML) and SVG.
1463
+# The default value is: HTML-CSS.
1464
+# This tag requires that the tag USE_MATHJAX is set to YES.
1465
+
1466
+MATHJAX_FORMAT         = HTML-CSS
1467
+
1468
+# When MathJax is enabled you need to specify the location relative to the HTML
1469
+# output directory using the MATHJAX_RELPATH option. The destination directory
1470
+# should contain the MathJax.js script. For instance, if the mathjax directory
1471
+# is located at the same level as the HTML output directory, then
1472
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
1473
+# Content Delivery Network so you can quickly see the result without installing
1474
+# MathJax. However, it is strongly recommended to install a local copy of
1475
+# MathJax from http://www.mathjax.org before deployment.
1476
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
1477
+# This tag requires that the tag USE_MATHJAX is set to YES.
1478
+
1479
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
1480
+
1481
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
1482
+# extension names that should be enabled during MathJax rendering. For example
1483
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
1484
+# This tag requires that the tag USE_MATHJAX is set to YES.
1485
+
1486
+MATHJAX_EXTENSIONS     =
1487
+
1488
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
1489
+# of code that will be used on startup of the MathJax code. See the MathJax site
1490
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
1491
+# example see the documentation.
1492
+# This tag requires that the tag USE_MATHJAX is set to YES.
1493
+
1494
+MATHJAX_CODEFILE       =
1495
+
1496
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
1497
+# the HTML output. The underlying search engine uses javascript and DHTML and
1498
+# should work on any modern browser. Note that when using HTML help
1499
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
1500
+# there is already a search function so this one should typically be disabled.
1501
+# For large projects the javascript based search engine can be slow, then
1502
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
1503
+# search using the keyboard; to jump to the search box use <access key> + S
1504
+# (what the <access key> is depends on the OS and browser, but it is typically
1505
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
1506
+# key> to jump into the search results window, the results can be navigated
1507
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
1508
+# the search. The filter options can be selected when the cursor is inside the
1509
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
1510
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
1511
+# option.
1512
+# The default value is: YES.
1513
+# This tag requires that the tag GENERATE_HTML is set to YES.
1514
+
1515
+SEARCHENGINE           = YES
1516
+
1517
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
1518
+# implemented using a web server instead of a web client using Javascript. There
1519
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
1520
+# setting. When disabled, doxygen will generate a PHP script for searching and
1521
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
1522
+# and searching needs to be provided by external tools. See the section
1523
+# "External Indexing and Searching" for details.
1524
+# The default value is: NO.
1525
+# This tag requires that the tag SEARCHENGINE is set to YES.
1526
+
1527
+SERVER_BASED_SEARCH    = NO
1528
+
1529
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
1530
+# script for searching. Instead the search results are written to an XML file
1531
+# which needs to be processed by an external indexer. Doxygen will invoke an
1532
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
1533
+# search results.
1534
+#
1535
+# Doxygen ships with an example indexer (doxyindexer) and search engine
1536
+# (doxysearch.cgi) which are based on the open source search engine library
1537
+# Xapian (see: http://xapian.org/).
1538
+#
1539
+# See the section "External Indexing and Searching" for details.
1540
+# The default value is: NO.
1541
+# This tag requires that the tag SEARCHENGINE is set to YES.
1542
+
1543
+EXTERNAL_SEARCH        = NO
1544
+
1545
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
1546
+# which will return the search results when EXTERNAL_SEARCH is enabled.
1547
+#
1548
+# Doxygen ships with an example indexer (doxyindexer) and search engine
1549
+# (doxysearch.cgi) which are based on the open source search engine library
1550
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
1551
+# Searching" for details.
1552
+# This tag requires that the tag SEARCHENGINE is set to YES.
1553
+
1554
+SEARCHENGINE_URL       =
1555
+
1556
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
1557
+# search data is written to a file for indexing by an external tool. With the
1558
+# SEARCHDATA_FILE tag the name of this file can be specified.
1559
+# The default file is: searchdata.xml.
1560
+# This tag requires that the tag SEARCHENGINE is set to YES.
1561
+
1562
+SEARCHDATA_FILE        = searchdata.xml
1563
+
1564
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
1565
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
1566
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
1567
+# projects and redirect the results back to the right project.
1568
+# This tag requires that the tag SEARCHENGINE is set to YES.
1569
+
1570
+EXTERNAL_SEARCH_ID     =
1571
+
1572
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
1573
+# projects other than the one defined by this configuration file, but that are
1574
+# all added to the same external search index. Each project needs to have a
1575
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
1576
+# to a relative location where the documentation can be found. The format is:
1577
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
1578
+# This tag requires that the tag SEARCHENGINE is set to YES.
1579
+
1580
+EXTRA_SEARCH_MAPPINGS  =
1581
+
1582
+#---------------------------------------------------------------------------
1583
+# Configuration options related to the LaTeX output
1584
+#---------------------------------------------------------------------------
1585
+
1586
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
1587
+# The default value is: YES.
1588
+
1589
+GENERATE_LATEX         = YES
1590
+
1591
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
1592
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1593
+# it.
1594
+# The default directory is: latex.
1595
+# This tag requires that the tag GENERATE_LATEX is set to YES.
1596
+
1597
+LATEX_OUTPUT           = latex
1598
+
1599
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
1600
+# invoked.
1601
+#
1602
+# Note that when enabling USE_PDFLATEX this option is only used for generating
1603
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
1604
+# written to the output directory.
1605
+# The default file is: latex.
1606
+# This tag requires that the tag GENERATE_LATEX is set to YES.
1607
+
1608
+LATEX_CMD_NAME         = latex
1609
+
1610
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
1611
+# index for LaTeX.
1612
+# The default file is: makeindex.
1613
+# This tag requires that the tag GENERATE_LATEX is set to YES.
1614
+
1615
+MAKEINDEX_CMD_NAME     = makeindex
1616
+
1617
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
1618
+# documents. This may be useful for small projects and may help to save some
1619
+# trees in general.
1620
+# The default value is: NO.
1621
+# This tag requires that the tag GENERATE_LATEX is set to YES.
1622
+
1623
+COMPACT_LATEX          = NO
1624
+
1625
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
1626
+# printer.
1627
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
1628
+# 14 inches) and executive (7.25 x 10.5 inches).
1629
+# The default value is: a4.
1630
+# This tag requires that the tag GENERATE_LATEX is set to YES.
1631
+
1632
+PAPER_TYPE             = a4
1633
+
1634
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
1635
+# that should be included in the LaTeX output. The package can be specified just
1636
+# by its name or with the correct syntax as to be used with the LaTeX
1637
+# \usepackage command. To get the times font for instance you can specify :
1638
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
1639
+# To use the option intlimits with the amsmath package you can specify:
1640
+# EXTRA_PACKAGES=[intlimits]{amsmath}
1641
+# If left blank no extra packages will be included.
1642
+# This tag requires that the tag GENERATE_LATEX is set to YES.
1643
+
1644
+EXTRA_PACKAGES         =
1645
+
1646
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
1647
+# generated LaTeX document. The header should contain everything until the first
1648
+# chapter. If it is left blank doxygen will generate a standard header. See
1649
+# section "Doxygen usage" for information on how to let doxygen write the
1650
+# default header to a separate file.
1651
+#
1652
+# Note: Only use a user-defined header if you know what you are doing! The
1653
+# following commands have a special meaning inside the header: $title,
1654
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
1655
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
1656
+# string, for the replacement values of the other commands the user is referred
1657
+# to HTML_HEADER.
1658
+# This tag requires that the tag GENERATE_LATEX is set to YES.
1659
+
1660
+LATEX_HEADER           =
1661
+
1662
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
1663
+# generated LaTeX document. The footer should contain everything after the last
1664
+# chapter. If it is left blank doxygen will generate a standard footer. See
1665
+# LATEX_HEADER for more information on how to generate a default footer and what
1666
+# special commands can be used inside the footer.
1667
+#
1668
+# Note: Only use a user-defined footer if you know what you are doing!
1669
+# This tag requires that the tag GENERATE_LATEX is set to YES.
1670
+
1671
+LATEX_FOOTER           =
1672
+
1673
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
1674
+# LaTeX style sheets that are included after the standard style sheets created
1675
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
1676
+# will copy the style sheet files to the output directory.
1677
+# Note: The order of the extra style sheet files is of importance (e.g. the last
1678
+# style sheet in the list overrules the setting of the previous ones in the
1679
+# list).
1680
+# This tag requires that the tag GENERATE_LATEX is set to YES.
1681
+
1682
+LATEX_EXTRA_STYLESHEET =
1683
+
1684
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
1685
+# other source files which should be copied to the LATEX_OUTPUT output
1686
+# directory. Note that the files will be copied as-is; there are no commands or
1687
+# markers available.
1688
+# This tag requires that the tag GENERATE_LATEX is set to YES.
1689
+
1690
+LATEX_EXTRA_FILES      =
1691
+
1692
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
1693
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
1694
+# contain links (just like the HTML output) instead of page references. This
1695
+# makes the output suitable for online browsing using a PDF viewer.
1696
+# The default value is: YES.
1697
+# This tag requires that the tag GENERATE_LATEX is set to YES.
1698
+
1699
+PDF_HYPERLINKS         = YES
1700
+
1701
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
1702
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
1703
+# higher quality PDF documentation.
1704
+# The default value is: YES.
1705
+# This tag requires that the tag GENERATE_LATEX is set to YES.
1706
+
1707
+USE_PDFLATEX           = YES
1708
+
1709
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
1710
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
1711
+# if errors occur, instead of asking the user for help. This option is also used
1712
+# when generating formulas in HTML.
1713
+# The default value is: NO.
1714
+# This tag requires that the tag GENERATE_LATEX is set to YES.
1715
+
1716
+LATEX_BATCHMODE        = NO
1717
+
1718
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
1719
+# index chapters (such as File Index, Compound Index, etc.) in the output.
1720
+# The default value is: NO.
1721
+# This tag requires that the tag GENERATE_LATEX is set to YES.
1722
+
1723
+LATEX_HIDE_INDICES     = NO
1724
+
1725
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
1726
+# code with syntax highlighting in the LaTeX output.
1727
+#
1728
+# Note that which sources are shown also depends on other settings such as
1729
+# SOURCE_BROWSER.
1730
+# The default value is: NO.
1731
+# This tag requires that the tag GENERATE_LATEX is set to YES.
1732
+
1733
+LATEX_SOURCE_CODE      = NO
1734
+
1735
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
1736
+# bibliography, e.g. plainnat, or ieeetr. See
1737
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
1738
+# The default value is: plain.
1739
+# This tag requires that the tag GENERATE_LATEX is set to YES.
1740
+
1741
+LATEX_BIB_STYLE        = plain
1742
+
1743
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
1744
+# page will contain the date and time when the page was generated. Setting this
1745
+# to NO can help when comparing the output of multiple runs.
1746
+# The default value is: NO.
1747
+# This tag requires that the tag GENERATE_LATEX is set to YES.
1748
+
1749
+LATEX_TIMESTAMP        = NO
1750
+
1751
+#---------------------------------------------------------------------------
1752
+# Configuration options related to the RTF output
1753
+#---------------------------------------------------------------------------
1754
+
1755
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
1756
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
1757
+# readers/editors.
1758
+# The default value is: NO.
1759
+
1760
+GENERATE_RTF           = NO
1761
+
1762
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
1763
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1764
+# it.
1765
+# The default directory is: rtf.
1766
+# This tag requires that the tag GENERATE_RTF is set to YES.
1767
+
1768
+RTF_OUTPUT             = rtf
1769
+
1770
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
1771
+# documents. This may be useful for small projects and may help to save some
1772
+# trees in general.
1773
+# The default value is: NO.
1774
+# This tag requires that the tag GENERATE_RTF is set to YES.
1775
+
1776
+COMPACT_RTF            = NO
1777
+
1778
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
1779
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
1780
+# output) instead of page references. This makes the output suitable for online
1781
+# browsing using Word or some other Word compatible readers that support those
1782
+# fields.
1783
+#
1784
+# Note: WordPad (write) and others do not support links.
1785
+# The default value is: NO.
1786
+# This tag requires that the tag GENERATE_RTF is set to YES.
1787
+
1788
+RTF_HYPERLINKS         = NO
1789
+
1790
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
1791
+# file, i.e. a series of assignments. You only have to provide replacements,
1792
+# missing definitions are set to their default value.
1793
+#
1794
+# See also section "Doxygen usage" for information on how to generate the
1795
+# default style sheet that doxygen normally uses.
1796
+# This tag requires that the tag GENERATE_RTF is set to YES.
1797
+
1798
+RTF_STYLESHEET_FILE    =
1799
+
1800
+# Set optional variables used in the generation of an RTF document. Syntax is
1801
+# similar to doxygen's config file. A template extensions file can be generated
1802
+# using doxygen -e rtf extensionFile.
1803
+# This tag requires that the tag GENERATE_RTF is set to YES.
1804
+
1805
+RTF_EXTENSIONS_FILE    =
1806
+
1807
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
1808
+# with syntax highlighting in the RTF output.
1809
+#
1810
+# Note that which sources are shown also depends on other settings such as
1811
+# SOURCE_BROWSER.
1812
+# The default value is: NO.
1813
+# This tag requires that the tag GENERATE_RTF is set to YES.
1814
+
1815
+RTF_SOURCE_CODE        = NO
1816
+
1817
+#---------------------------------------------------------------------------
1818
+# Configuration options related to the man page output
1819
+#---------------------------------------------------------------------------
1820
+
1821
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
1822
+# classes and files.
1823
+# The default value is: NO.
1824
+
1825
+GENERATE_MAN           = NO
1826
+
1827
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
1828
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1829
+# it. A directory man3 will be created inside the directory specified by
1830
+# MAN_OUTPUT.
1831
+# The default directory is: man.
1832
+# This tag requires that the tag GENERATE_MAN is set to YES.
1833
+
1834
+MAN_OUTPUT             = man
1835
+
1836
+# The MAN_EXTENSION tag determines the extension that is added to the generated
1837
+# man pages. In case the manual section does not start with a number, the number
1838
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
1839
+# optional.
1840
+# The default value is: .3.
1841
+# This tag requires that the tag GENERATE_MAN is set to YES.
1842
+
1843
+MAN_EXTENSION          = .3
1844
+
1845
+# The MAN_SUBDIR tag determines the name of the directory created within
1846
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
1847
+# MAN_EXTENSION with the initial . removed.
1848
+# This tag requires that the tag GENERATE_MAN is set to YES.
1849
+
1850
+MAN_SUBDIR             =
1851
+
1852
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
1853
+# will generate one additional man file for each entity documented in the real
1854
+# man page(s). These additional files only source the real man page, but without
1855
+# them the man command would be unable to find the correct page.
1856
+# The default value is: NO.
1857
+# This tag requires that the tag GENERATE_MAN is set to YES.
1858
+
1859
+MAN_LINKS              = NO
1860
+
1861
+#---------------------------------------------------------------------------
1862
+# Configuration options related to the XML output
1863
+#---------------------------------------------------------------------------
1864
+
1865
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
1866
+# captures the structure of the code including all documentation.
1867
+# The default value is: NO.
1868
+
1869
+GENERATE_XML           = NO
1870
+
1871
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
1872
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1873
+# it.
1874
+# The default directory is: xml.
1875
+# This tag requires that the tag GENERATE_XML is set to YES.
1876
+
1877
+XML_OUTPUT             = xml
1878
+
1879
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
1880
+# listings (including syntax highlighting and cross-referencing information) to
1881
+# the XML output. Note that enabling this will significantly increase the size
1882
+# of the XML output.
1883
+# The default value is: YES.
1884
+# This tag requires that the tag GENERATE_XML is set to YES.
1885
+
1886
+XML_PROGRAMLISTING     = YES
1887
+
1888
+#---------------------------------------------------------------------------
1889
+# Configuration options related to the DOCBOOK output
1890
+#---------------------------------------------------------------------------
1891
+
1892
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
1893
+# that can be used to generate PDF.
1894
+# The default value is: NO.
1895
+
1896
+GENERATE_DOCBOOK       = NO
1897
+
1898
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
1899
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
1900
+# front of it.
1901
+# The default directory is: docbook.
1902
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
1903
+
1904
+DOCBOOK_OUTPUT         = docbook
1905
+
1906
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
1907
+# program listings (including syntax highlighting and cross-referencing
1908
+# information) to the DOCBOOK output. Note that enabling this will significantly
1909
+# increase the size of the DOCBOOK output.
1910
+# The default value is: NO.
1911
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
1912
+
1913
+DOCBOOK_PROGRAMLISTING = NO
1914
+
1915
+#---------------------------------------------------------------------------
1916
+# Configuration options for the AutoGen Definitions output
1917
+#---------------------------------------------------------------------------
1918
+
1919
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
1920
+# AutoGen Definitions (see http://autogen.sf.net) file that captures the
1921
+# structure of the code including all documentation. Note that this feature is
1922
+# still experimental and incomplete at the moment.
1923
+# The default value is: NO.
1924
+
1925
+GENERATE_AUTOGEN_DEF   = NO
1926
+
1927
+#---------------------------------------------------------------------------
1928
+# Configuration options related to the Perl module output
1929
+#---------------------------------------------------------------------------
1930
+
1931
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
1932
+# file that captures the structure of the code including all documentation.
1933
+#
1934
+# Note that this feature is still experimental and incomplete at the moment.
1935
+# The default value is: NO.
1936
+
1937
+GENERATE_PERLMOD       = NO
1938
+
1939
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
1940
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
1941
+# output from the Perl module output.
1942
+# The default value is: NO.
1943
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
1944
+
1945
+PERLMOD_LATEX          = NO
1946
+
1947
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
1948
+# formatted so it can be parsed by a human reader. This is useful if you want to
1949
+# understand what is going on. On the other hand, if this tag is set to NO, the
1950
+# size of the Perl module output will be much smaller and Perl will parse it
1951
+# just the same.
1952
+# The default value is: YES.
1953
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
1954
+
1955
+PERLMOD_PRETTY         = YES
1956
+
1957
+# The names of the make variables in the generated doxyrules.make file are
1958
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
1959
+# so different doxyrules.make files included by the same Makefile don't
1960
+# overwrite each other's variables.
1961
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
1962
+
1963
+PERLMOD_MAKEVAR_PREFIX =
1964
+
1965
+#---------------------------------------------------------------------------
1966
+# Configuration options related to the preprocessor
1967
+#---------------------------------------------------------------------------
1968
+
1969
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
1970
+# C-preprocessor directives found in the sources and include files.
1971
+# The default value is: YES.
1972
+
1973
+ENABLE_PREPROCESSING   = YES
1974
+
1975
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
1976
+# in the source code. If set to NO, only conditional compilation will be
1977
+# performed. Macro expansion can be done in a controlled way by setting
1978
+# EXPAND_ONLY_PREDEF to YES.
1979
+# The default value is: NO.
1980
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1981
+
1982
+MACRO_EXPANSION        = NO
1983
+
1984
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
1985
+# the macro expansion is limited to the macros specified with the PREDEFINED and
1986
+# EXPAND_AS_DEFINED tags.
1987
+# The default value is: NO.
1988
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1989
+
1990
+EXPAND_ONLY_PREDEF     = NO
1991
+
1992
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
1993
+# INCLUDE_PATH will be searched if a #include is found.
1994
+# The default value is: YES.
1995
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1996
+
1997
+SEARCH_INCLUDES        = YES
1998
+
1999
+# The INCLUDE_PATH tag can be used to specify one or more directories that
2000
+# contain include files that are not input files but should be processed by the
2001
+# preprocessor.
2002
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
2003
+
2004
+INCLUDE_PATH           =
2005
+
2006
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
2007
+# patterns (like *.h and *.hpp) to filter out the header-files in the
2008
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
2009
+# used.
2010
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
2011
+
2012
+INCLUDE_FILE_PATTERNS  =
2013
+
2014
+# The PREDEFINED tag can be used to specify one or more macro names that are
2015
+# defined before the preprocessor is started (similar to the -D option of e.g.
2016
+# gcc). The argument of the tag is a list of macros of the form: name or
2017
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
2018
+# is assumed. To prevent a macro definition from being undefined via #undef or
2019
+# recursively expanded use the := operator instead of the = operator.
2020
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
2021
+
2022
+PREDEFINED             =
2023
+
2024
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
2025
+# tag can be used to specify a list of macro names that should be expanded. The
2026
+# macro definition that is found in the sources will be used. Use the PREDEFINED
2027
+# tag if you want to use a different macro definition that overrules the
2028
+# definition found in the source code.
2029
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
2030
+
2031
+EXPAND_AS_DEFINED      =
2032
+
2033
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
2034
+# remove all references to function-like macros that are alone on a line, have
2035
+# an all uppercase name, and do not end with a semicolon. Such function macros
2036
+# are typically used for boiler-plate code, and will confuse the parser if not
2037
+# removed.
2038
+# The default value is: YES.
2039
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
2040
+
2041
+SKIP_FUNCTION_MACROS   = YES
2042
+
2043
+#---------------------------------------------------------------------------
2044
+# Configuration options related to external references
2045
+#---------------------------------------------------------------------------
2046
+
2047
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
2048
+# file the location of the external documentation should be added. The format of
2049
+# a tag file without this location is as follows:
2050
+# TAGFILES = file1 file2 ...
2051
+# Adding location for the tag files is done as follows:
2052
+# TAGFILES = file1=loc1 "file2 = loc2" ...
2053
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
2054
+# section "Linking to external documentation" for more information about the use
2055
+# of tag files.
2056
+# Note: Each tag file must have a unique name (where the name does NOT include
2057
+# the path). If a tag file is not located in the directory in which doxygen is
2058
+# run, you must also specify the path to the tagfile here.
2059
+
2060
+TAGFILES               =
2061
+
2062
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
2063
+# tag file that is based on the input files it reads. See section "Linking to
2064
+# external documentation" for more information about the usage of tag files.
2065
+
2066
+GENERATE_TAGFILE       =
2067
+
2068
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
2069
+# the class index. If set to NO, only the inherited external classes will be
2070
+# listed.
2071
+# The default value is: NO.
2072
+
2073
+ALLEXTERNALS           = NO
2074
+
2075
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
2076
+# in the modules index. If set to NO, only the current project's groups will be
2077
+# listed.
2078
+# The default value is: YES.
2079
+
2080
+EXTERNAL_GROUPS        = YES
2081
+
2082
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
2083
+# the related pages index. If set to NO, only the current project's pages will
2084
+# be listed.
2085
+# The default value is: YES.
2086
+
2087
+EXTERNAL_PAGES         = YES
2088
+
2089
+# The PERL_PATH should be the absolute path and name of the perl script
2090
+# interpreter (i.e. the result of 'which perl').
2091
+# The default file (with absolute path) is: /usr/bin/perl.
2092
+
2093
+PERL_PATH              = /usr/bin/perl
2094
+
2095
+#---------------------------------------------------------------------------
2096
+# Configuration options related to the dot tool
2097
+#---------------------------------------------------------------------------
2098
+
2099
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
2100
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
2101
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
2102
+# disabled, but it is recommended to install and use dot, since it yields more
2103
+# powerful graphs.
2104
+# The default value is: YES.
2105
+
2106
+CLASS_DIAGRAMS         = YES
2107
+
2108
+# You can define message sequence charts within doxygen comments using the \msc
2109
+# command. Doxygen will then run the mscgen tool (see:
2110
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
2111
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
2112
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
2113
+# default search path.
2114
+
2115
+MSCGEN_PATH            =
2116
+
2117
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
2118
+# then run dia to produce the diagram and insert it in the documentation. The
2119
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
2120
+# If left empty dia is assumed to be found in the default search path.
2121
+
2122
+DIA_PATH               =
2123
+
2124
+# If set to YES the inheritance and collaboration graphs will hide inheritance
2125
+# and usage relations if the target is undocumented or is not a class.
2126
+# The default value is: YES.
2127
+
2128
+HIDE_UNDOC_RELATIONS   = YES
2129
+
2130
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
2131
+# available from the path. This tool is part of Graphviz (see:
2132
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
2133
+# Bell Labs. The other options in this section have no effect if this option is
2134
+# set to NO
2135
+# The default value is: NO.
2136
+
2137
+HAVE_DOT               = NO
2138
+
2139
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
2140
+# to run in parallel. When set to 0 doxygen will base this on the number of
2141
+# processors available in the system. You can set it explicitly to a value
2142
+# larger than 0 to get control over the balance between CPU load and processing
2143
+# speed.
2144
+# Minimum value: 0, maximum value: 32, default value: 0.
2145
+# This tag requires that the tag HAVE_DOT is set to YES.
2146
+
2147
+DOT_NUM_THREADS        = 0
2148
+
2149
+# When you want a differently looking font in the dot files that doxygen
2150
+# generates you can specify the font name using DOT_FONTNAME. You need to make
2151
+# sure dot is able to find the font, which can be done by putting it in a
2152
+# standard location or by setting the DOTFONTPATH environment variable or by
2153
+# setting DOT_FONTPATH to the directory containing the font.
2154
+# The default value is: Helvetica.
2155
+# This tag requires that the tag HAVE_DOT is set to YES.
2156
+
2157
+DOT_FONTNAME           = Helvetica
2158
+
2159
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
2160
+# dot graphs.
2161
+# Minimum value: 4, maximum value: 24, default value: 10.
2162
+# This tag requires that the tag HAVE_DOT is set to YES.
2163
+
2164
+DOT_FONTSIZE           = 10
2165
+
2166
+# By default doxygen will tell dot to use the default font as specified with
2167
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
2168
+# the path where dot can find it using this tag.
2169
+# This tag requires that the tag HAVE_DOT is set to YES.
2170
+
2171
+DOT_FONTPATH           =
2172
+
2173
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
2174
+# each documented class showing the direct and indirect inheritance relations.
2175
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
2176
+# The default value is: YES.
2177
+# This tag requires that the tag HAVE_DOT is set to YES.
2178
+
2179
+CLASS_GRAPH            = YES
2180
+
2181
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
2182
+# graph for each documented class showing the direct and indirect implementation
2183
+# dependencies (inheritance, containment, and class references variables) of the
2184
+# class with other documented classes.
2185
+# The default value is: YES.
2186
+# This tag requires that the tag HAVE_DOT is set to YES.
2187
+
2188
+COLLABORATION_GRAPH    = YES
2189
+
2190
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
2191
+# groups, showing the direct groups dependencies.
2192
+# The default value is: YES.
2193
+# This tag requires that the tag HAVE_DOT is set to YES.
2194
+
2195
+GROUP_GRAPHS           = YES
2196
+
2197
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
2198
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
2199
+# Language.
2200
+# The default value is: NO.
2201
+# This tag requires that the tag HAVE_DOT is set to YES.
2202
+
2203
+UML_LOOK               = NO
2204
+
2205
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
2206
+# class node. If there are many fields or methods and many nodes the graph may
2207
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
2208
+# number of items for each type to make the size more manageable. Set this to 0
2209
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
2210
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
2211
+# but if the number exceeds 15, the total amount of fields shown is limited to
2212
+# 10.
2213
+# Minimum value: 0, maximum value: 100, default value: 10.
2214
+# This tag requires that the tag HAVE_DOT is set to YES.
2215
+
2216
+UML_LIMIT_NUM_FIELDS   = 10
2217
+
2218
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
2219
+# collaboration graphs will show the relations between templates and their
2220
+# instances.
2221
+# The default value is: NO.
2222
+# This tag requires that the tag HAVE_DOT is set to YES.
2223
+
2224
+TEMPLATE_RELATIONS     = NO
2225
+
2226
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
2227
+# YES then doxygen will generate a graph for each documented file showing the
2228
+# direct and indirect include dependencies of the file with other documented
2229
+# files.
2230
+# The default value is: YES.
2231
+# This tag requires that the tag HAVE_DOT is set to YES.
2232
+
2233
+INCLUDE_GRAPH          = YES
2234
+
2235
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
2236
+# set to YES then doxygen will generate a graph for each documented file showing
2237
+# the direct and indirect include dependencies of the file with other documented
2238
+# files.
2239
+# The default value is: YES.
2240
+# This tag requires that the tag HAVE_DOT is set to YES.
2241
+
2242
+INCLUDED_BY_GRAPH      = YES
2243
+
2244
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
2245
+# dependency graph for every global function or class method.
2246
+#
2247
+# Note that enabling this option will significantly increase the time of a run.
2248
+# So in most cases it will be better to enable call graphs for selected
2249
+# functions only using the \callgraph command. Disabling a call graph can be
2250
+# accomplished by means of the command \hidecallgraph.
2251
+# The default value is: NO.
2252
+# This tag requires that the tag HAVE_DOT is set to YES.
2253
+
2254
+CALL_GRAPH             = NO
2255
+
2256
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
2257
+# dependency graph for every global function or class method.
2258
+#
2259
+# Note that enabling this option will significantly increase the time of a run.
2260
+# So in most cases it will be better to enable caller graphs for selected
2261
+# functions only using the \callergraph command. Disabling a caller graph can be
2262
+# accomplished by means of the command \hidecallergraph.
2263
+# The default value is: NO.
2264
+# This tag requires that the tag HAVE_DOT is set to YES.
2265
+
2266
+CALLER_GRAPH           = NO
2267
+
2268
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
2269
+# hierarchy of all classes instead of a textual one.
2270
+# The default value is: YES.
2271
+# This tag requires that the tag HAVE_DOT is set to YES.
2272
+
2273
+GRAPHICAL_HIERARCHY    = YES
2274
+
2275
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
2276
+# dependencies a directory has on other directories in a graphical way. The
2277
+# dependency relations are determined by the #include relations between the
2278
+# files in the directories.
2279
+# The default value is: YES.
2280
+# This tag requires that the tag HAVE_DOT is set to YES.
2281
+
2282
+DIRECTORY_GRAPH        = YES
2283
+
2284
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
2285
+# generated by dot. For an explanation of the image formats see the section
2286
+# output formats in the documentation of the dot tool (Graphviz (see:
2287
+# http://www.graphviz.org/)).
2288
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
2289
+# to make the SVG files visible in IE 9+ (other browsers do not have this
2290
+# requirement).
2291
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
2292
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
2293
+# png:gdiplus:gdiplus.
2294
+# The default value is: png.
2295
+# This tag requires that the tag HAVE_DOT is set to YES.
2296
+
2297
+DOT_IMAGE_FORMAT       = png
2298
+
2299
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
2300
+# enable generation of interactive SVG images that allow zooming and panning.
2301
+#
2302
+# Note that this requires a modern browser other than Internet Explorer. Tested
2303
+# and working are Firefox, Chrome, Safari, and Opera.
2304
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
2305
+# the SVG files visible. Older versions of IE do not have SVG support.
2306
+# The default value is: NO.
2307
+# This tag requires that the tag HAVE_DOT is set to YES.
2308
+
2309
+INTERACTIVE_SVG        = NO
2310
+
2311
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
2312
+# found. If left blank, it is assumed the dot tool can be found in the path.
2313
+# This tag requires that the tag HAVE_DOT is set to YES.
2314
+
2315
+DOT_PATH               =
2316
+
2317
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
2318
+# contain dot files that are included in the documentation (see the \dotfile
2319
+# command).
2320
+# This tag requires that the tag HAVE_DOT is set to YES.
2321
+
2322
+DOTFILE_DIRS           =
2323
+
2324
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
2325
+# contain msc files that are included in the documentation (see the \mscfile
2326
+# command).
2327
+
2328
+MSCFILE_DIRS           =
2329
+
2330
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
2331
+# contain dia files that are included in the documentation (see the \diafile
2332
+# command).
2333
+
2334
+DIAFILE_DIRS           =
2335
+
2336
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
2337
+# path where java can find the plantuml.jar file. If left blank, it is assumed
2338
+# PlantUML is not used or called during a preprocessing step. Doxygen will
2339
+# generate a warning when it encounters a \startuml command in this case and
2340
+# will not generate output for the diagram.
2341
+
2342
+PLANTUML_JAR_PATH      =
2343
+
2344
+# When using plantuml, the specified paths are searched for files specified by
2345
+# the !include statement in a plantuml block.
2346
+
2347
+PLANTUML_INCLUDE_PATH  =
2348
+
2349
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
2350
+# that will be shown in the graph. If the number of nodes in a graph becomes
2351
+# larger than this value, doxygen will truncate the graph, which is visualized
2352
+# by representing a node as a red box. Note that doxygen if the number of direct
2353
+# children of the root node in a graph is already larger than
2354
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
2355
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
2356
+# Minimum value: 0, maximum value: 10000, default value: 50.
2357
+# This tag requires that the tag HAVE_DOT is set to YES.
2358
+
2359
+DOT_GRAPH_MAX_NODES    = 50
2360
+
2361
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
2362
+# generated by dot. A depth value of 3 means that only nodes reachable from the
2363
+# root by following a path via at most 3 edges will be shown. Nodes that lay
2364
+# further from the root node will be omitted. Note that setting this option to 1
2365
+# or 2 may greatly reduce the computation time needed for large code bases. Also
2366
+# note that the size of a graph can be further restricted by
2367
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
2368
+# Minimum value: 0, maximum value: 1000, default value: 0.
2369
+# This tag requires that the tag HAVE_DOT is set to YES.
2370
+
2371
+MAX_DOT_GRAPH_DEPTH    = 0
2372
+
2373
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
2374
+# background. This is disabled by default, because dot on Windows does not seem
2375
+# to support this out of the box.
2376
+#
2377
+# Warning: Depending on the platform used, enabling this option may lead to
2378
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
2379
+# read).
2380
+# The default value is: NO.
2381
+# This tag requires that the tag HAVE_DOT is set to YES.
2382
+
2383
+DOT_TRANSPARENT        = NO
2384
+
2385
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
2386
+# files in one run (i.e. multiple -o and -T options on the command line). This
2387
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
2388
+# this, this feature is disabled by default.
2389
+# The default value is: NO.
2390
+# This tag requires that the tag HAVE_DOT is set to YES.
2391
+
2392
+DOT_MULTI_TARGETS      = NO
2393
+
2394
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
2395
+# explaining the meaning of the various boxes and arrows in the dot generated
2396
+# graphs.
2397
+# The default value is: YES.
2398
+# This tag requires that the tag HAVE_DOT is set to YES.
2399
+
2400
+GENERATE_LEGEND        = YES
2401
+
2402
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
2403
+# files that are used to generate the various graphs.
2404
+# The default value is: YES.
2405
+# This tag requires that the tag HAVE_DOT is set to YES.
2406
+
2407
+DOT_CLEANUP            = YES
2408
obs-studio-0.17.0.tar.xz/deps/libcaption/LICENSE.txt Added
23
 
1
@@ -0,0 +1,21 @@
2
+The MIT License
3
+
4
+Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.
5
+
6
+Permission is hereby granted, free of charge, to any person obtaining a copy
7
+of this software and associated documentation files (the "Software"), to deal
8
+in the Software without restriction, including without limitation the rights
9
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+copies of the Software, and to permit persons to whom the Software is
11
+furnished to do so, subject to the following conditions:
12
+
13
+The above copyright notice and this permission notice shall be included in
14
+all copies or substantial portions of the Software.
15
+
16
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+THE SOFTWARE.
23
obs-studio-0.17.0.tar.xz/deps/libcaption/README.md Added
101
 
1
@@ -0,0 +1,99 @@
2
+# version
3
+v0.6
4
+Matthew Szatmary m3u8@twitch.tv / matt@szatmary.org
5
+
6
+# libcaption
7
+
8
+libcaption is a small library written in C to aid in the creating and parsing of closed caption data for use in the twitch player, open sourced to use within community developed broadcast tools. To maintain consistency across platforms libcaption aims to implement a subset of EIA608, CEA708 as supported by the Apple iOS platform.
9
+
10
+608 support is currently limited to encoding and decoding the necessary control and preamble codes as well as support for the Basic North American, Special North American and Extended Western European character sets.
11
+
12
+708 support is limited to encoding the 608 data in NTSC field 1 user data type structure.
13
+
14
+In addition, utility functions to create h.264 SEI (Supplementary enhancement information) NALUs (Network Abstraction Layer Unit) for inclusion into an h.264 elementary stream are provided.
15
+
16
+H.264 utility functions are limited to wrapping the 708 payload into a SEI NALU. This is accomplished by prepending the 708 payload with 3 bytes (nal_unit_type = 6, payloadType = 4, and PayloadSize = variable), and appending a stop bit encoded into a full byte (with a value of 127). In addition if the 708 payload contains an emulated start code, a three byte sequence equaling 0,0,1 an emulation prevention byte (3) is inserted. Functions to reverse this operation are also provided.
17
+
18
+## Characters
19
+| | | | | | | | | | | | | | | | | |
20
+|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
21
+|BNA| |!|"|#|$|%|&|’|(|)|á|+|,|-|.|/|
22
+|BNA|0|1|2|3|4|5|6|7|8|9|:|;|<|=|>|?|
23
+|BNA|@|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|
24
+|BNA|P|Q|R|S|T|U|V|W|X|Y|Z|[|é|]|í|ó|
25
+|BNA|ú|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|
26
+|BNA|p|q|r|s|t|u|v|w|x|y|z|ç|÷|Ñ|ñ|█|
27
+|SNA|®|°|½|¿|™|¢|£|♪|à| |è|â|ê|î|ô|û|
28
+|WES|Á|É|Ó|Ú|Ü|ü|‘|¡|*|'|—|©|℠|•|“|”|
29
+|WEF|À|Â|Ç|È|Ê|Ë|ë|Î|Ï|ï|Ô|Ù|ù|Û|«|»|
30
+|WEP|Ã|ã|Í|Ì|ì|Ò|ò|Õ|õ|{|}|\\|^|_|\||~|
31
+|WEG|Ä|ä|Ö|ö|ß|¥|¤|¦|Å|å|Ø|ø|┌|┐|└|┘|
32
+
33
+* BNA = Basic North American character set
34
+* SNA = Special North American character set
35
+* WES = Extended Western European character set : Extended Spanish/Miscellaneous
36
+* WEF = Extended Western European character set : Extended French
37
+* WEP = Extended Western European character set : Portuguese
38
+* WEG = Extended Western European character set : German/Danish
39
+
40
+
41
+------
42
+eia608_screen_t is the default internal representation. `screens` can be
43
+converted to and from SEI messages 608/708 buffers and SRT files
44
+
45
+## JSON format
46
+A JSON rendered format is provided for convenience of integration. The JSON
47
+format is as follows:
48
+
49
+```
50
+{
51
+    "format":  "eia608",
52
+    "mode":    "pop-on",
53
+    "roll-up": 0,
54
+    "data": [
55
+        { "row":0, "col":0, "char":"A", "style":"white" },
56
+        { "row":0, "col":1, "char":"B", "style":"white" },
57
+        // ...
58
+    ]
59
+}
60
+```
61
+
62
+### `format`
63
+The only current valid value is `"eia608"`. This field exists for
64
+future expansion.  Any values other than `"eia608"`, and the object should be
65
+ignored for now.
66
+
67
+### `mode`
68
+Defines the method by which screen contents are adjusted in response to
69
+new data, such as content in excess of the normal grid size.
70
+
71
+Possible modes are:
72
+
73
+`"clear"`: Generated when a screen is initialized, but not entered a "loading"
74
+state. `"clear"` mode  occurs frequently when the display is to be erased.
75
+
76
+`"pop-on"`: Normally used for pre recorded content where. A pop-on screen should
77
+completely replace all previous screen contents.
78
+
79
+`"paint-on"`: Normally used for live content. In this mode, new characters
80
+appear one or two at a time. The `data` array does include the complete state of
81
+the screen. In practice, it may not be different that `"pop-on"`.
82
+
83
+An internal "loading" mode also exists.
84
+
85
+### `roll-up`
86
+Normally used for live content such as news broadcasts. Text is moved up the
87
+screen as new rows appear. The number of rows to be displayed is also encoded in
88
+the JSON  key `"roll-up"` where value is an integer of `0`, `1`, `2`, `3`, or `4`.
89
+Like `"paint-on"`, the `data` array does include the complete state of the screen.
90
+
91
+### `data`
92
+Contains a object for every character to be displayed. The screen is a grid of
93
+15 rows and 32 columns. The position of the character is available in the `row`
94
+and `col` fields. The character itself is in the `char` field. The full
95
+character set is available in the document, but any valid UTF-8 should be
96
+supported for future. The style field will contain one of the following values:
97
+
98
+`"white"`, `"green"`, `"blue"`, `"cyan"`, `"red"`, `"yellow"`, `"magenta"`, `"italics"`
99
+
100
+Characters with the `"italics"` style should be displayed in white.
101
obs-studio-0.17.0.tar.xz/deps/libcaption/caption Added
2
 
1
+(directory)
2
obs-studio-0.17.0.tar.xz/deps/libcaption/caption/avc.h Added
200
 
1
@@ -0,0 +1,198 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#ifndef LIBCAPTION_AVC_H
26
+#define LIBCAPTION_AVC_H
27
+#include "cea708.h"
28
+#include "caption.h"
29
+#include <float.h>
30
+////////////////////////////////////////////////////////////////////////////////
31
+#define MAX_NALU_SIZE (4*1024*1024)
32
+typedef struct {
33
+    size_t size;
34
+    uint8_t data[MAX_NALU_SIZE];
35
+} avcnalu_t;
36
+
37
+void avcnalu_init (avcnalu_t* nalu);
38
+int avcnalu_parse_annexb (avcnalu_t* nalu, const uint8_t** data, size_t* size);
39
+static inline uint8_t  avcnalu_type (avcnalu_t* nalu) { return nalu->data[0] & 0x1F; }
40
+static inline uint8_t* avcnalu_data (avcnalu_t* nalu) { return &nalu->data[0]; }
41
+static inline size_t   avcnalu_size (avcnalu_t* nalu) { return nalu->size; }
42
+////////////////////////////////////////////////////////////////////////////////
43
+typedef struct _sei_message_t sei_message_t;
44
+
45
+typedef enum {
46
+    sei_type_buffering_period = 0,
47
+    sei_type_pic_timing = 1,
48
+    sei_type_pan_scan_rect = 2,
49
+    sei_type_filler_payload = 3,
50
+    sei_type_user_data_registered_itu_t_t35 = 4,
51
+    sei_type_user_data_unregistered = 5,
52
+    sei_type_recovery_point = 6,
53
+    sei_type_dec_ref_pic_marking_repetition = 7,
54
+    sei_type_spare_pic = 8,
55
+    sei_type_scene_info = 9,
56
+    sei_type_sub_seq_info = 10,
57
+    sei_type_sub_seq_layer_characteristics = 11,
58
+    sei_type_sub_seq_characteristics = 12,
59
+    sei_type_full_frame_freeze = 13,
60
+    sei_type_full_frame_freeze_release = 14,
61
+    sei_type_full_frame_snapshot = 15,
62
+    sei_type_progressive_refinement_segment_start = 16,
63
+    sei_type_progressive_refinement_segment_end = 17,
64
+    sei_type_motion_constrained_slice_group_set = 18,
65
+    sei_type_film_grain_characteristics = 19,
66
+    sei_type_deblocking_filter_display_preference = 20,
67
+    sei_type_stereo_video_info = 21,
68
+} sei_msgtype_t;
69
+////////////////////////////////////////////////////////////////////////////////
70
+// time in seconds
71
+typedef struct  {
72
+    double dts;
73
+    double cts;
74
+    sei_message_t* head;
75
+    sei_message_t* tail;
76
+} sei_t;
77
+
78
+/*! \brief
79
+    \param
80
+*/
81
+void sei_init (sei_t* sei);
82
+/*! \brief
83
+    \param
84
+*/
85
+void sei_free (sei_t* sei);
86
+/*! \brief
87
+    \param
88
+*/
89
+static inline double sei_dts (sei_t* sei) { return sei->dts; }
90
+static inline double sei_cts (sei_t* sei) { return sei->cts; }
91
+static inline double sei_pts (sei_t* sei) { return sei->dts + sei->cts; }
92
+/*! \brief
93
+    \param
94
+*/
95
+int sei_parse_nalu (sei_t* sei, const uint8_t* data, size_t size, double dts, double cts);
96
+/*! \brief
97
+    \param
98
+*/
99
+// TODO add dts,cts to nalu
100
+static inline int sei_parse_avcnalu (sei_t* sei, avcnalu_t* nalu, double dts, double cts) { return sei_parse_nalu (sei,avcnalu_data (nalu),avcnalu_size (nalu),dts,cts); }
101
+/*! \brief
102
+    \param
103
+*/
104
+static inline int sei_finish (sei_t* sei) { return sei_parse_nalu (sei,0,0,0.0,DBL_MAX); }
105
+/*! \brief
106
+    \param
107
+*/
108
+static inline sei_message_t* sei_message_head (sei_t* sei) { return sei->head; }
109
+/*! \brief
110
+    \param
111
+*/
112
+static inline sei_message_t* sei_message_tail (sei_t* sei) { return sei->tail; }
113
+/*! \brief
114
+    \param
115
+*/
116
+sei_message_t* sei_message_next (sei_message_t* msg);
117
+/*! \brief
118
+    \param
119
+*/
120
+sei_msgtype_t sei_message_type (sei_message_t* msg);
121
+/*! \brief
122
+    \param
123
+*/
124
+size_t sei_message_size (sei_message_t* msg);
125
+/*! \brief
126
+    \param
127
+*/
128
+uint8_t* sei_message_data (sei_message_t* msg);
129
+/*! \brief
130
+    \param
131
+*/
132
+sei_message_t* sei_message_new (sei_msgtype_t type, uint8_t* data, size_t size);
133
+/*! \brief
134
+    \param
135
+*/
136
+static inline sei_message_t* sei_message_copy (sei_message_t* msg)
137
+{
138
+    return sei_message_new (sei_message_type (msg), sei_message_data (msg), sei_message_size (msg));
139
+}
140
+/**
141
+Free message and all accoiated data. Messaged added to sei_t by using sei_append_message MUST NOT be freed
142
+These messages will be freed by calling sei_free()
143
+*/
144
+/*! \brief
145
+    \param
146
+*/
147
+void  sei_message_free (sei_message_t* msg);
148
+////////////////////////////////////////////////////////////////////////////////
149
+/*! \brief
150
+    \param
151
+*/
152
+static inline int sei_decode_cea708 (sei_message_t* msg, cea708_t* cea708)
153
+{
154
+    if (sei_type_user_data_registered_itu_t_t35 == sei_message_type (msg)) {
155
+        return cea708_parse (sei_message_data (msg), sei_message_size (msg), cea708);
156
+    } else {
157
+        return 0;
158
+    }
159
+}
160
+////////////////////////////////////////////////////////////////////////////////
161
+/*! \brief
162
+    \param
163
+*/
164
+size_t sei_render_size (sei_t* sei);
165
+/*! \brief
166
+    \param
167
+*/
168
+size_t sei_render (sei_t* sei, uint8_t* data);
169
+/*! \brief
170
+    \param
171
+*/
172
+void sei_dump (sei_t* sei);
173
+/*! \brief
174
+    \param
175
+*/
176
+void sei_dump_messages (sei_message_t* head);
177
+////////////////////////////////////////////////////////////////////////////////
178
+/*! \brief
179
+    \param
180
+*/
181
+int sei_from_caption_frame (sei_t* sei, caption_frame_t* frame);
182
+/*! \brief
183
+    \param
184
+*/
185
+libcaption_stauts_t sei_to_caption_frame (sei_t* sei, caption_frame_t* frame);
186
+/*! \brief
187
+    \param
188
+*/
189
+static inline int nalu_to_caption_frame (caption_frame_t* frame, const uint8_t* data, size_t size, double pts, double dts)
190
+{
191
+    sei_t sei;
192
+    sei_init (&sei);
193
+    sei_parse_nalu (&sei, data, size, pts, dts);
194
+    sei_to_caption_frame (&sei,frame);
195
+    sei_free (&sei);
196
+    return 1;
197
+}
198
+////////////////////////////////////////////////////////////////////////////////
199
+#endif
200
obs-studio-0.17.0.tar.xz/deps/libcaption/caption/caption.h Added
143
 
1
@@ -0,0 +1,141 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#ifndef LIBCAPTION_H
26
+#define LIBCAPTION_H
27
+#include "utf8.h"
28
+#include "xds.h"
29
+#include "eia608.h"
30
+
31
+// ssize_t is POSIX and does not exist on Windows
32
+#if defined(_MSC_VER)
33
+#if defined(_WIN64)
34
+typedef signed long ssize_t;
35
+#else
36
+typedef signed int ssize_t;
37
+#endif
38
+#endif
39
+
40
+typedef enum {
41
+    LIBCAPTION_OK = 1,
42
+    LIBCAPTION_ERROR = 0,
43
+    LIBCAPTION_READY = 2
44
+} libcaption_stauts_t;
45
+
46
+
47
+/*! \brief
48
+    \param
49
+*/
50
+static inline libcaption_stauts_t libcaption_status_update (libcaption_stauts_t old_stat, libcaption_stauts_t new_stat) { return (LIBCAPTION_ERROR == old_stat || LIBCAPTION_ERROR == new_stat) ? LIBCAPTION_ERROR : (LIBCAPTION_READY == old_stat) ? LIBCAPTION_READY : new_stat;  }
51
+
52
+#define SCREEN_ROWS 15
53
+#define SCREEN_COLS 32
54
+
55
+typedef struct {
56
+    unsigned int uln : 1; //< underline
57
+    unsigned int sty : 3; //< style
58
+    utf8_char_t data[5];  //< 4 byte utf8 values plus null term
59
+}  caption_frame_cell_t;
60
+
61
+typedef struct {
62
+    caption_frame_cell_t cell[SCREEN_ROWS][SCREEN_COLS];
63
+} caption_frame_buffer_t;
64
+
65
+
66
+typedef struct  {
67
+    unsigned int uln : 1; //< underline
68
+    unsigned int sty : 3; //< style
69
+    unsigned int mod : 3; //< current mode
70
+    unsigned int rup : 2; //< roll-up line count minus 1
71
+    uint16_t row, col, cc_data;
72
+} caption_frame_state_t;
73
+
74
+// timestamp and duration are in seconds
75
+typedef struct {
76
+    double timestamp;
77
+    double duration;
78
+    xds_t xds;
79
+    caption_frame_state_t state;
80
+    caption_frame_buffer_t front;
81
+    caption_frame_buffer_t back;
82
+} caption_frame_t;
83
+
84
+// typedef enum {
85
+//     eia608_paint_on = 0,
86
+//     eia608_pop_on   = 1,
87
+//     eia608_rollup_2 = 2,
88
+//     eia608_rollup_3 = 3,
89
+//     eia608_rollup_4 = 4,
90
+// } eia608_display_mode_t;
91
+// eia608_display_mode_t caption_frame_mode (caption_frame_t* frame);
92
+
93
+
94
+/*!
95
+    \brief Initializes an allocated caption_frame_t instance
96
+    \param frame Pointer to prealocated caption_frame_t object
97
+*/
98
+void caption_frame_init (caption_frame_t* frame);
99
+/*! \brief Writes a single charcter to a caption_frame_t object
100
+    \param frame A pointer to an allocted and initialized caption_frame_t object
101
+    \param row Row position to write charcter, must be between 0 and SCREEN_ROWS-1
102
+    \param col Column position to write charcter, must be between 0 and SCREEN_ROWS-1
103
+    \param style Style to apply to charcter
104
+    \param underline Set underline attribute, 0 = off any other value = on
105
+    \param c pointer to a single valid utf8 charcter. Bytes are automatically determined, and a NULL terminator is not required
106
+*/
107
+int caption_frame_write_char (caption_frame_t* frame, int row, int col, eia608_style_t style, int underline, const utf8_char_t* c);
108
+/*! \brief
109
+    \param
110
+*/
111
+const utf8_char_t* caption_frame_read_char (caption_frame_t* frame, int row, int col, eia608_style_t* style, int* underline);
112
+/*! \brief
113
+    \param
114
+*/
115
+
116
+/*! \brief
117
+    \param
118
+*/
119
+libcaption_stauts_t caption_frame_decode (caption_frame_t* frame, uint16_t cc_data, double timestamp);
120
+
121
+/*! \brief
122
+    \param
123
+*/
124
+int caption_frame_from_text (caption_frame_t* frame, const utf8_char_t* data);
125
+/*! \brief
126
+    \param
127
+*/
128
+#define CAPTION_FRAME_TEXT_BYTES (((2+SCREEN_ROWS)*SCREEN_COLS*4)+1)
129
+void caption_frame_to_text (caption_frame_t* frame, utf8_char_t* data);
130
+/*! \brief
131
+    \param
132
+*/
133
+#define CAPTION_FRAME_DUMP_BUF_SIZE 4096
134
+size_t caption_frame_dump_buffer (caption_frame_t* frame, utf8_char_t* buf);
135
+void caption_frame_dump (caption_frame_t* frame);
136
+/*! \brief
137
+    \param
138
+*/
139
+#define CAPTION_FRAME_JSON_BUF_SIZE 32768
140
+size_t caption_frame_json (caption_frame_t* frame, utf8_char_t* buf);
141
+
142
+#endif
143
obs-studio-0.17.0.tar.xz/deps/libcaption/caption/cea708.h Added
112
 
1
@@ -0,0 +1,110 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#ifndef LIBCAPTION_CEA708_H
26
+#define LIBCAPTION_CEA708_H
27
+
28
+#include "caption.h"
29
+#define CEA608_MAX_SIZE (255)
30
+
31
+////////////////////////////////////////////////////////////////////////////////
32
+typedef enum {
33
+    cc_type_ntsc_cc_field_1 = 0,
34
+    cc_type_ntsc_cc_field_2 = 1,
35
+    cc_type_dtvcc_packet_data = 2,
36
+    cc_type_dtvcc_packet_start = 3,
37
+} cea708_cc_type_t;
38
+
39
+typedef struct {
40
+    unsigned int marker_bits : 5;
41
+    unsigned int cc_valid : 1;
42
+    unsigned int cc_type : 2; // castable to cea708_cc_type_t
43
+    unsigned int cc_data : 16;
44
+} cc_data_t;
45
+
46
+typedef struct {
47
+    unsigned int process_em_data_flag : 1;
48
+    unsigned int process_cc_data_flag : 1;
49
+    unsigned int additional_data_flag : 1;
50
+    unsigned int cc_count : 5;
51
+    unsigned int em_data : 8;
52
+    cc_data_t cc_data[32];
53
+} user_data_t;
54
+
55
+/*! \brief
56
+    \param
57
+*/
58
+cc_data_t cea708_encode_cc_data (int cc_valid, cea708_cc_type_t type, uint16_t cc_data);
59
+/*! \brief
60
+    \param
61
+*/
62
+int cea708_cc_count (user_data_t* data);
63
+/*! \brief
64
+    \param
65
+*/
66
+uint16_t cea708_cc_data (user_data_t* data, int index, int* valid, cea708_cc_type_t* type);
67
+////////////////////////////////////////////////////////////////////////////////
68
+
69
+typedef enum {
70
+    country_united_states = 181,
71
+} itu_t_t35_country_code_t;
72
+
73
+typedef enum {
74
+    t35_provider_direct_tv = 47,
75
+    t35_provider_atsc = 49,
76
+} itu_t_t35_provider_code_t;
77
+
78
+typedef struct {
79
+    itu_t_t35_country_code_t country;
80
+    itu_t_t35_provider_code_t provider;
81
+    uint32_t user_identifier;
82
+    uint8_t atsc1_data_user_data_type_code;
83
+    uint8_t directv_user_data_length;
84
+    user_data_t user_data;
85
+} cea708_t;
86
+
87
+/*! \brief
88
+    \param
89
+*/
90
+int cea708_init (cea708_t* cea708); // will confgure using HLS compatiable defaults
91
+/*! \brief
92
+    \param
93
+*/
94
+int cea708_parse (uint8_t* data, size_t size, cea708_t* cea708);
95
+/*! \brief
96
+    \param
97
+*/
98
+libcaption_stauts_t cea708_to_caption_frame (caption_frame_t* frame, cea708_t* cea708, double pts);
99
+/*! \brief
100
+    \param
101
+*/
102
+int cea708_add_cc_data (cea708_t* cea708, int valid, cea708_cc_type_t type, uint16_t cc_data);
103
+/*! \brief
104
+    \param
105
+*/
106
+int cea708_render (cea708_t* cea708, uint8_t* data, size_t size);
107
+/*! \brief
108
+    \param
109
+*/
110
+void cea708_dump (cea708_t* cea708);
111
+#endif
112
obs-studio-0.17.0.tar.xz/deps/libcaption/caption/eia608.h Added
208
 
1
@@ -0,0 +1,206 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#ifndef LIBCAPTION_EIA608_H
26
+#define LIBCAPTION_EIA608_H
27
+
28
+#include "utf8.h"
29
+#include "eia608_charmap.h"
30
+////////////////////////////////////////////////////////////////////////////////
31
+// Parity
32
+#define EIA608_BX(B,X) (((B)>>X)&0x01)
33
+#define EIA608_BP(B) ((B)&0x7F) | ((EIA608_BX((B),0)^EIA608_BX(B,1)^EIA608_BX((B),2)^EIA608_BX((B),3)^EIA608_BX((B),4)^EIA608_BX((B),5)^EIA608_BX((B),6)^(0x01))<<7)
34
+#define EIA608_B2(B) EIA608_BP((B)+0), EIA608_BP((B)+1), EIA608_BP((B)+2), EIA608_BP((B)+3), EIA608_BP((B)+4), EIA608_BP((B)+5), EIA608_BP((B)+6), EIA608_BP((B)+7)
35
+#define EIA608_B1(B) EIA608_B2((B)+0), EIA608_B2((B)+8), EIA608_B2((B)+16), EIA608_B2((B)+24), EIA608_B2((B)+32), EIA608_B2((B)+40), EIA608_B2((B)+48), EIA608_B2((B)+56)
36
+
37
+static const uint8_t eia608_parity_table[] = { EIA608_B1 (0), EIA608_B1 (64) };
38
+extern const char* eia608_mode_map[];
39
+extern const char* eia608_style_map[];
40
+
41
+#ifdef _MSC_VER
42
+#ifndef inline
43
+#define inline __inline
44
+#endif
45
+#endif
46
+
47
+/*! \brief
48
+    \param
49
+*/
50
+static inline uint8_t  eia608_parity_byte (uint8_t cc_data) { return eia608_parity_table[0x7F & cc_data]; }
51
+/*! \brief
52
+    \param
53
+*/
54
+static inline uint16_t eia608_parity_word (uint16_t cc_data) { return (uint16_t) ( (eia608_parity_byte ( (uint8_t) (cc_data>>8)) <<8) | eia608_parity_byte ( (uint8_t) cc_data)); }
55
+/*! \brief
56
+    \param
57
+*/
58
+static inline uint16_t eia608_parity (uint16_t cc_data) { return eia608_parity_word (cc_data); }
59
+/*! \brief
60
+    \param
61
+*/
62
+static inline int eia608_parity_varify (uint16_t cc_data) { return eia608_parity_word (cc_data) == cc_data ? 1 : 0; }
63
+/*! \brief
64
+    \param
65
+*/
66
+static inline int eia608_parity_strip (uint16_t cc_data) { return cc_data & 0x7F7F; }
67
+/*! \brief
68
+    \param
69
+*/
70
+static inline int eia608_test_second_channel_bit (uint16_t cc_data) { return (cc_data & 0x0800); }
71
+
72
+////////////////////////////////////////////////////////////////////////////////
73
+// cc_data types
74
+/*! \brief
75
+    \param
76
+*/
77
+static inline int eia608_is_basicna (uint16_t cc_data) { return 0x0000 != (0x6000 & cc_data); /*&& 0x1F00 < (0x7F00 & cc_data);*/ }
78
+/*! \brief
79
+    \param
80
+*/
81
+static inline int eia608_is_preamble (uint16_t cc_data) { return 0x1040 == (0x7040 & cc_data); }
82
+/*! \brief
83
+    \param
84
+*/
85
+static inline int eia608_is_midrowchange (uint16_t cc_data) { return 0x1120 == (0x7770 & cc_data); }
86
+/*! \brief
87
+    \param
88
+*/
89
+static inline int eia608_is_specialna (uint16_t cc_data) { return 0x1130 == (0x7770 & cc_data); }
90
+/*! \brief
91
+    \param
92
+*/
93
+static inline int eia608_is_xds (uint16_t cc_data) { return 0x0000 == (0x7070 & cc_data) && 0x0000 != (0x0F0F & cc_data); }
94
+/*! \brief
95
+    \param
96
+*/
97
+static inline int eia608_is_westeu (uint16_t cc_data) { return 0x1220 == (0x7660 & cc_data); }
98
+/*! \brief
99
+    \param
100
+*/
101
+static inline int eia608_is_control (uint16_t cc_data) { return 0x1420 == (0x7670 & cc_data) || 0x1720 == (0x7770 & cc_data); }
102
+/*! \brief
103
+    \param
104
+*/
105
+static inline int eia608_is_norpak (uint16_t cc_data) { return 0x1724 == (0x777C & cc_data) || 0x1728 == (0x777C & cc_data); }
106
+/*! \brief
107
+    \param
108
+*/
109
+static inline int eia608_is_padding (uint16_t cc_data) { return 0x8080 == cc_data; }
110
+
111
+////////////////////////////////////////////////////////////////////////////////
112
+// preamble
113
+typedef enum {
114
+    eia608_style_white = 0,
115
+    eia608_style_green = 1,
116
+    eia608_style_blue = 2,
117
+    eia608_style_cyan = 3,
118
+    eia608_style_red = 4,
119
+    eia608_style_yellow = 5,
120
+    eia608_style_magenta = 6,
121
+    eia608_style_italics = 7,
122
+} eia608_style_t;
123
+
124
+/*! \brief
125
+    \param
126
+*/
127
+int eia608_parse_preamble (uint16_t cc_data, int* row, int* col, eia608_style_t* style, int* chan, int* underline);
128
+/*! \brief
129
+    \param
130
+*/
131
+int eia608_parse_midrowchange (uint16_t cc_data, int* chan, eia608_style_t* style, int* underline);
132
+/*! \brief
133
+    \param
134
+*/
135
+uint16_t eia608_row_column_pramble (int row, int col, int chan, int underline);
136
+/*! \brief
137
+    \param
138
+*/
139
+uint16_t eia608_row_style_pramble (int row, eia608_style_t style, int chan, int underline);
140
+
141
+////////////////////////////////////////////////////////////////////////////////
142
+// control command
143
+typedef enum { // yes, no?
144
+    eia608_tab_offset_0 = 0x1720,
145
+    eia608_tab_offset_1 = 0x1721,
146
+    eia608_tab_offset_2 = 0x1722,
147
+    eia608_tab_offset_3 = 0x1723,
148
+    eia608_control_resume_caption_loading = 0x1420,
149
+    eia608_control_backspace = 0x1421,
150
+    eia608_control_alarm_off = 0x1422,
151
+    eia608_control_alarm_on = 0x1423,
152
+    eia608_control_delete_to_end_of_row = 0x1424,
153
+    eia608_control_roll_up_2 = 0x1425,
154
+    eia608_control_roll_up_3 = 0x1426,
155
+    eia608_control_roll_up_4 = 0x1427,
156
+    eia608_control_resume_direct_captioning = 0x1429,
157
+    eia608_control_text_restart = 0x142A,
158
+    eia608_control_text_resume_text_display = 0x142B,
159
+    eia608_control_erase_display_memory = 0x142C,
160
+    eia608_control_carriage_return = 0x142D,
161
+    eia608_control_erase_non_displayed_memory = 0x142E,
162
+    eia608_control_end_of_caption = 0x142F,
163
+} eia608_control_t;
164
+
165
+#define eia608_control_popon eia608_control_resume_caption_loading
166
+#define eia608_control_painton eia608_control_resume_direct_captioning
167
+
168
+/*! \brief
169
+    \param
170
+*/
171
+uint16_t eia608_control_command (eia608_control_t cmd, int cc);
172
+/*! \brief
173
+    \param
174
+*/
175
+static inline uint16_t eia608_tab (int size, int cc) { return eia608_control_command ( (eia608_control_t) (eia608_tab_offset_0 | (size&0x0F)),cc); }
176
+/*! \brief
177
+    \param
178
+*/
179
+eia608_control_t eia608_parse_control (uint16_t cc_data, int* cc);
180
+
181
+////////////////////////////////////////////////////////////////////////////////
182
+// text
183
+/*! \brief
184
+    \param c
185
+*/
186
+uint16_t eia608_from_utf8_1 (const utf8_char_t* c, int chan);
187
+/*! \brief
188
+    \param
189
+*/
190
+uint16_t eia608_from_utf8_2 (const utf8_char_t* c1, const utf8_char_t* c2);
191
+/*! \brief
192
+    \param
193
+*/
194
+uint16_t eia608_from_basicna (uint16_t bna1, uint16_t bna2);
195
+/*! \brief
196
+    \param
197
+*/
198
+int eia608_to_utf8 (uint16_t c, int* chan, utf8_char_t* char1, utf8_char_t* char2);
199
+////////////////////////////////////////////////////////////////////////////////
200
+/*! \brief
201
+    \param
202
+*/
203
+void eia608_dump (uint16_t cc_data);
204
+////////////////////////////////////////////////////////////////////////////////
205
+
206
+
207
+#endif
208
obs-studio-0.17.0.tar.xz/deps/libcaption/caption/eia608_charmap.h Added
232
 
1
@@ -0,0 +1,230 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#ifndef LIBCAPTION_EIA608_CHARMAP_H
26
+#define LIBCAPTION_EIA608_CHARMAP_H
27
+
28
+#define EIA608_CHAR_COUNT 176
29
+extern const char* eia608_char_map[EIA608_CHAR_COUNT];
30
+
31
+// Helper char
32
+#define EIA608_CHAR_NULL                                       ""
33
+// Basic North American character set
34
+#define EIA608_CHAR_SPACE                                      "\x20"
35
+#define EIA608_CHAR_EXCLAMATION_MARK                           "\x21"
36
+#define EIA608_CHAR_QUOTATION_MARK                             "\x22"
37
+#define EIA608_CHAR_NUMBER_SIGN                                "\x23"
38
+#define EIA608_CHAR_DOLLAR_SIGN                                "\x24"
39
+#define EIA608_CHAR_PERCENT_SIGN                               "\x25"
40
+#define EIA608_CHAR_AMPERSAND                                  "\x26"
41
+#define EIA608_CHAR_LEFT_SINGLE_QUOTATION_MARK                 "\xE2\x80\x98"
42
+#define EIA608_CHAR_LEFT_PARENTHESIS                           "\x28"
43
+#define EIA608_CHAR_RIGHT_PARENTHESIS                          "\x29"
44
+#define EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_ACUTE            "\xC3\xA1"
45
+#define EIA608_CHAR_PLUS_SIGN                                  "\x2B"
46
+#define EIA608_CHAR_COMMA                                      "\x2C"
47
+#define EIA608_CHAR_HYPHEN_MINUS                               "\x2D"
48
+#define EIA608_CHAR_FULL_STOP                                  "\x2E"
49
+#define EIA608_CHAR_SOLIDUS                                    "\x2F"
50
+
51
+// Basic North American character set
52
+#define EIA608_CHAR_DIGIT_ZERO                                 "\x30"
53
+#define EIA608_CHAR_DIGIT_ONE                                  "\x31"
54
+#define EIA608_CHAR_DIGIT_TWO                                  "\x32"
55
+#define EIA608_CHAR_DIGIT_THREE                                "\x33"
56
+#define EIA608_CHAR_DIGIT_FOUR                                 "\x34"
57
+#define EIA608_CHAR_DIGIT_FIVE                                 "\x35"
58
+#define EIA608_CHAR_DIGIT_SIX                                  "\x36"
59
+#define EIA608_CHAR_DIGIT_SEVEN                                "\x37"
60
+#define EIA608_CHAR_DIGIT_EIGHT                                "\x38"
61
+#define EIA608_CHAR_DIGIT_NINE                                 "\x39"
62
+#define EIA608_CHAR_COLON                                      "\x3A"
63
+#define EIA608_CHAR_SEMICOLON                                  "\x3B"
64
+#define EIA608_CHAR_LESS_THAN_SIGN                             "\x3C"
65
+#define EIA608_CHAR_EQUALS_SIGN                                "\x3D"
66
+#define EIA608_CHAR_GREATER_THAN_SIGN                          "\x3E"
67
+#define EIA608_CHAR_QUESTION_MARK                              "\x3F"
68
+
69
+// Basic North American character set
70
+#define EIA608_CHAR_COMMERCIAL_AT                              "\x40"
71
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_A                     "\x41"
72
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_B                     "\x42"
73
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_C                     "\x43"
74
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_D                     "\x44"
75
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_E                     "\x45"
76
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_F                     "\x46"
77
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_G                     "\x47"
78
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_H                     "\x48"
79
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_I                     "\x49"
80
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_J                     "\x4A"
81
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_K                     "\x4B"
82
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_L                     "\x4C"
83
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_M                     "\x4D"
84
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_N                     "\x4E"
85
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_O                     "\x4F"
86
+
87
+// Basic North American character set
88
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_P                     "\x50"
89
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_Q                     "\x51"
90
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_R                     "\x52"
91
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_S                     "\x53"
92
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_T                     "\x54"
93
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_U                     "\x55"
94
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_V                     "\x56"
95
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_W                     "\x57"
96
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_X                     "\x58"
97
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_Y                     "\x59"
98
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_Z                     "\x5A"
99
+#define EIA608_CHAR_LEFT_SQUARE_BRACKET                        "\x5B"
100
+#define EIA608_CHAR_LATIN_SMALL_LETTER_E_WITH_ACUTE            "\xC3\xA9"
101
+#define EIA608_CHAR_RIGHT_SQUARE_BRACKET                       "\x5D"
102
+#define EIA608_CHAR_LATIN_SMALL_LETTER_I_WITH_ACUTE            "\xC3\xAD"
103
+#define EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_ACUTE            "\xC3\xB3"
104
+
105
+// Basic North American character set
106
+#define EIA608_CHAR_LATIN_SMALL_LETTER_U_WITH_ACUTE            "\xC3\xBA"
107
+#define EIA608_CHAR_LATIN_SMALL_LETTER_A                       "\x61"
108
+#define EIA608_CHAR_LATIN_SMALL_LETTER_B                       "\x62"
109
+#define EIA608_CHAR_LATIN_SMALL_LETTER_C                       "\x63"
110
+#define EIA608_CHAR_LATIN_SMALL_LETTER_D                       "\x64"
111
+#define EIA608_CHAR_LATIN_SMALL_LETTER_E                       "\x65"
112
+#define EIA608_CHAR_LATIN_SMALL_LETTER_F                       "\x66"
113
+#define EIA608_CHAR_LATIN_SMALL_LETTER_G                       "\x67"
114
+#define EIA608_CHAR_LATIN_SMALL_LETTER_H                       "\x68"
115
+#define EIA608_CHAR_LATIN_SMALL_LETTER_I                       "\x69"
116
+#define EIA608_CHAR_LATIN_SMALL_LETTER_J                       "\x6A"
117
+#define EIA608_CHAR_LATIN_SMALL_LETTER_K                       "\x6B"
118
+#define EIA608_CHAR_LATIN_SMALL_LETTER_L                       "\x6C"
119
+#define EIA608_CHAR_LATIN_SMALL_LETTER_M                       "\x6D"
120
+#define EIA608_CHAR_LATIN_SMALL_LETTER_N                       "\x6E"
121
+#define EIA608_CHAR_LATIN_SMALL_LETTER_O                       "\x6F"
122
+
123
+// Basic North American character set
124
+#define EIA608_CHAR_LATIN_SMALL_LETTER_P                       "\x70"
125
+#define EIA608_CHAR_LATIN_SMALL_LETTER_Q                       "\x71"
126
+#define EIA608_CHAR_LATIN_SMALL_LETTER_R                       "\x72"
127
+#define EIA608_CHAR_LATIN_SMALL_LETTER_S                       "\x73"
128
+#define EIA608_CHAR_LATIN_SMALL_LETTER_T                       "\x74"
129
+#define EIA608_CHAR_LATIN_SMALL_LETTER_U                       "\x75"
130
+#define EIA608_CHAR_LATIN_SMALL_LETTER_V                       "\x76"
131
+#define EIA608_CHAR_LATIN_SMALL_LETTER_W                       "\x77"
132
+#define EIA608_CHAR_LATIN_SMALL_LETTER_X                       "\x78"
133
+#define EIA608_CHAR_LATIN_SMALL_LETTER_Y                       "\x79"
134
+#define EIA608_CHAR_LATIN_SMALL_LETTER_Z                       "\x7A"
135
+#define EIA608_CHAR_LATIN_SMALL_LETTER_C_WITH_CEDILLA          "\xC3\xA7"
136
+#define EIA608_CHAR_DIVISION_SIGN                              "\xC3\xB7"
137
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_N_WITH_TILDE          "\xC3\x91"
138
+#define EIA608_CHAR_LATIN_SMALL_LETTER_N_WITH_TILDE            "\xC3\xB1"
139
+#define EIA608_CHAR_FULL_BLOCK                                 "\xE2\x96\x88"
140
+
141
+// Special North American character set[edit]
142
+#define EIA608_CHAR_REGISTERED_SIGN                            "\xC2\xAE"
143
+#define EIA608_CHAR_DEGREE_SIGN                                "\xC2\xB0"
144
+#define EIA608_CHAR_VULGAR_FRACTION_ONE_HALF                   "\xC2\xBD"
145
+#define EIA608_CHAR_INVERTED_QUESTION_MARK                     "\xC2\xBF"
146
+#define EIA608_CHAR_TRADE_MARK_SIGN                            "\xE2\x84\xA2"
147
+#define EIA608_CHAR_CENT_SIGN                                  "\xC2\xA2"
148
+#define EIA608_CHAR_POUND_SIGN                                 "\xC2\xA3"
149
+#define EIA608_CHAR_EIGHTH_NOTE                                "\xE2\x99\xAA"
150
+#define EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_GRAVE            "\xC3\xA0"
151
+#define EIA608_CHAR_NO_BREAK_SPACE                             "\xC2\xA0"
152
+#define EIA608_CHAR_LATIN_SMALL_LETTER_E_WITH_GRAVE            "\xC3\xA8"
153
+#define EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_CIRCUMFLEX       "\xC3\xA2"
154
+#define EIA608_CHAR_LATIN_SMALL_LETTER_E_WITH_CIRCUMFLEX       "\xC3\xAA"
155
+#define EIA608_CHAR_LATIN_SMALL_LETTER_I_WITH_CIRCUMFLEX       "\xC3\xAE"
156
+#define EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_CIRCUMFLEX       "\xC3\xB4"
157
+#define EIA608_CHAR_LATIN_SMALL_LETTER_U_WITH_CIRCUMFLEX       "\xC3\xBB"
158
+
159
+// Extended Western European character set : Extended Spanish/Miscellaneous
160
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_ACUTE          "\xC3\x81"
161
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_E_WITH_ACUTE          "\xC3\x89"
162
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_ACUTE          "\xC3\x93"
163
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_U_WITH_ACUTE          "\xC3\x9A"
164
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_U_WITH_DIAERESIS      "\xC3\x9C"
165
+#define EIA608_CHAR_LATIN_SMALL_LETTER_U_WITH_DIAERESIS        "\xC3\xBC"
166
+#define EIA608_CHAR_RIGHT_SINGLE_QUOTATION_MARK                "\xE2\x80\x99"
167
+#define EIA608_CHAR_INVERTED_EXCLAMATION_MARK                  "\xC2\xA1"
168
+#define EIA608_CHAR_ASTERISK                                   "\x2A"
169
+#define EIA608_CHAR_APOSTROPHE                                 "\x27"
170
+#define EIA608_CHAR_EM_DASH                                    "\xE2\x80\x94"
171
+#define EIA608_CHAR_COPYRIGHT_SIGN                             "\xC2\xA9"
172
+#define EIA608_CHAR_SERVICE_MARK                               "\xE2\x84\xA0"
173
+#define EIA608_CHAR_BULLET                                     "\xE2\x80\xA2"
174
+#define EIA608_CHAR_LEFT_DOUBLE_QUOTATION_MARK                 "\xE2\x80\x9C"
175
+#define EIA608_CHAR_RIGHT_DOUBLE_QUOTATION_MARK                "\xE2\x80\x9D"
176
+
177
+// Extended Western European character set : Extended French
178
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_GRAVE          "\xC3\x80"
179
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_CIRCUMFLEX     "\xC3\x82"
180
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_C_WITH_CEDILLA        "\xC3\x87"
181
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_E_WITH_GRAVE          "\xC3\x88"
182
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_E_WITH_CIRCUMFLEX     "\xC3\x8A"
183
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_E_WITH_DIAERESIS      "\xC3\x8B"
184
+#define EIA608_CHAR_LATIN_SMALL_LETTER_E_WITH_DIAERESIS        "\xC3\xAB"
185
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_I_WITH_CIRCUMFLEX     "\xC3\x8E"
186
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_I_WITH_DIAERESIS      "\xC3\x8F"
187
+#define EIA608_CHAR_LATIN_SMALL_LETTER_I_WITH_DIAERESIS        "\xC3\xAF"
188
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_CIRCUMFLEX     "\xC3\x94"
189
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_U_WITH_GRAVE          "\xC3\x99"
190
+#define EIA608_CHAR_LATIN_SMALL_LETTER_U_WITH_GRAVE            "\xC3\xB9"
191
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_U_WITH_CIRCUMFLEX     "\xC3\x9B"
192
+#define EIA608_CHAR_LEFT_POINTING_DOUBLE_ANGLE_QUOTATION_MARK  "\xC2\xAB"
193
+#define EIA608_CHAR_RIGHT_POINTING_DOUBLE_ANGLE_QUOTATION_MARK "\xC2\xBB"
194
+
195
+// Extended Western European character set : Portuguese
196
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_TILDE          "\xC3\x83"
197
+#define EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_TILDE            "\xC3\xA3"
198
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_I_WITH_ACUTE          "\xC3\x8D"
199
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_I_WITH_GRAVE          "\xC3\x8C"
200
+#define EIA608_CHAR_LATIN_SMALL_LETTER_I_WITH_GRAVE            "\xC3\xAC"
201
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_GRAVE          "\xC3\x92"
202
+#define EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_GRAVE            "\xC3\xB2"
203
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_TILDE          "\xC3\x95"
204
+#define EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_TILDE            "\xC3\xB5"
205
+#define EIA608_CHAR_LEFT_CURLY_BRACKET                         "\x7B"
206
+#define EIA608_CHAR_RIGHT_CURLY_BRACKET                        "\x7D"
207
+#define EIA608_CHAR_REVERSE_SOLIDUS                            "\x5C"
208
+#define EIA608_CHAR_CIRCUMFLEX_ACCENT                          "\x5E"
209
+#define EIA608_CHAR_LOW_LINE                                   "\x5F"
210
+#define EIA608_CHAR_VERTICAL_LINE                              "\x7C"
211
+#define EIA608_CHAR_TILDE                                      "\x7E"
212
+
213
+// Extended Western European character set : German/Danish
214
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_DIAERESIS      "\xC3\x84"
215
+#define EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_DIAERESIS        "\xC3\xA4"
216
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_DIAERESIS      "\xC3\x96"
217
+#define EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_DIAERESIS        "\xC3\xB6"
218
+#define EIA608_CHAR_LATIN_SMALL_LETTER_SHARP_S                 "\xC3\x9F"
219
+#define EIA608_CHAR_YEN_SIGN                                   "\xC2\xA5"
220
+#define EIA608_CHAR_CURRENCY_SIGN                              "\xC2\xA4"
221
+#define EIA608_CHAR_BROKEN_BAR                                 "\xC2\xA6"
222
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_RING_ABOVE     "\xC3\x85"
223
+#define EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_RING_ABOVE       "\xC3\xA5"
224
+#define EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_STROKE         "\xC3\x98"
225
+#define EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_STROKE           "\xC3\xB8"
226
+#define EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_RIGHT          "\xE2\x94\x8C" // top left
227
+#define EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_LEFT           "\xE2\x94\x90" // top right
228
+#define EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_RIGHT            "\xE2\x94\x94" // lower left
229
+#define EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_LEFT             "\xE2\x94\x98" // bottom right
230
+
231
+#endif
232
obs-studio-0.17.0.tar.xz/deps/libcaption/caption/scc.h Added
33
 
1
@@ -0,0 +1,31 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#ifndef LIBCAPTION_SCC_H
26
+#define LIBCAPTION_SCC_H
27
+
28
+#include "eia608.h"
29
+
30
+int scc_to_608 (const char* line, double* pts, uint16_t* cc, int cc_max);
31
+
32
+#endif
33
obs-studio-0.17.0.tar.xz/deps/libcaption/caption/srt.h Added
89
 
1
@@ -0,0 +1,87 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#ifndef LIBCAPTION_SRT_H
26
+#define LIBCAPTION_SRT_H
27
+
28
+#include "eia608.h"
29
+#include "caption.h"
30
+
31
+// timestamp and duration are in seconds
32
+typedef struct _srt_t {
33
+    struct _srt_t* next;
34
+    double timestamp;
35
+    double duration;
36
+    size_t aloc;
37
+} srt_t;
38
+
39
+
40
+
41
+
42
+/*! \brief
43
+    \param
44
+*/
45
+srt_t* srt_new (const utf8_char_t* data, size_t size, double timestamp, srt_t* prev, srt_t** head);
46
+/*! \brief
47
+    \param
48
+*/
49
+srt_t* srt_free_head (srt_t* head);
50
+// returns the head of the link list. must bee freed when done
51
+/*! \brief
52
+    \param
53
+*/
54
+srt_t* srt_parse (const utf8_char_t* data, size_t size);
55
+/*! \brief
56
+    \param
57
+*/
58
+void srt_free (srt_t* srt);
59
+
60
+/*! \brief
61
+    \param
62
+*/
63
+static inline srt_t* srt_next (srt_t* srt) { return srt->next; }
64
+/*! \brief
65
+    \param
66
+*/
67
+static inline utf8_char_t* srt_data (srt_t* srt) { return (utf8_char_t*) (srt) + sizeof (srt_t); }
68
+// This only converts teh surrent SRT, It does not walk the list
69
+/*! \brief
70
+    \param
71
+*/
72
+int srt_to_caption_frame (srt_t* srt, caption_frame_t* frame);
73
+
74
+// returns teh new srt. Head is not tracher internally.
75
+/*! \brief
76
+    \param
77
+*/
78
+srt_t* srt_from_caption_frame (caption_frame_t* frame, srt_t* prev, srt_t** head);
79
+/*! \brief
80
+    \param
81
+*/
82
+void srt_dump (srt_t* srt);
83
+/*! \brief
84
+    \param
85
+*/
86
+void vtt_dump (srt_t* srt);
87
+
88
+#endif
89
obs-studio-0.17.0.tar.xz/deps/libcaption/caption/utf8.h Added
99
 
1
@@ -0,0 +1,97 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#ifndef LIBCAPTION_UTF8_H
26
+#define LIBCAPTION_UTF8_H
27
+
28
+#include <stddef.h>
29
+#include <inttypes.h>
30
+
31
+// These types exist to make the code more self dcoumenting
32
+// utf8_char_t point is a null teminate string of utf8 encodecd chars
33
+//
34
+// utf8_size_t is the length of a string in chars
35
+// size_t is bytes
36
+typedef char utf8_char_t;
37
+typedef size_t utf8_size_t;
38
+/*! \brief
39
+    \param
40
+
41
+    Skiped continuation bytes
42
+*/
43
+const utf8_char_t* utf8_char_next (const char* s);
44
+/*! \brief
45
+    \param
46
+
47
+    returnes the length of the char in bytes
48
+*/
49
+size_t utf8_char_length (const utf8_char_t* c);
50
+
51
+/*! \brief
52
+    \param
53
+
54
+    returns length of the string in bytes
55
+    size is number of charcter to count (0 to count until NULL term)
56
+*/
57
+size_t utf8_string_length (const utf8_char_t* data, utf8_size_t size);
58
+/*! \brief
59
+    \param
60
+*/
61
+size_t utf8_char_copy (utf8_char_t* dst, const utf8_char_t* src);
62
+
63
+/*! \brief
64
+    \param
65
+
66
+    returnes the number of utf8 charcters in a string givne the numbe of bytes
67
+    to coutn until the a null terminator, pass 0 for size
68
+*/
69
+utf8_size_t utf8_char_count (const char* data, size_t size);
70
+/*! \brief
71
+    \param
72
+
73
+    returnes the length of the line in bytes triming not printable charcters at the end
74
+*/
75
+size_t utf8_trimmed_length (const char* data, size_t size);
76
+/*! \brief
77
+    \param
78
+
79
+    returns the length in bytes of the line including the new line charcter(s)
80
+    auto detects between windows(CRLF), unix(LF), mac(CR) and riscos (LFCR) line endings
81
+*/
82
+size_t utf8_line_length (const char* data);
83
+/*! \brief
84
+    \param
85
+
86
+    returns number of chars to include before split
87
+*/
88
+utf8_size_t utf8_wrap_length (const utf8_char_t* data, utf8_size_t size);
89
+
90
+/*! \brief
91
+    \param
92
+
93
+    returns number of new lins in teh string
94
+*/
95
+int utf8_line_count (const utf8_char_t* data);
96
+
97
+
98
+#endif
99
obs-studio-0.17.0.tar.xz/deps/libcaption/caption/xds.h Added
34
 
1
@@ -0,0 +1,32 @@
2
+/**********************************************************************************************/
3
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
4
+/*                                                                                            */
5
+/* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file  */
6
+/* except in compliance with the License. A copy of the License is located at                 */
7
+/*                                                                                            */
8
+/*     http://aws.amazon.com/apache2.0/                                                       */
9
+/*                                                                                            */
10
+/* or in the "license" file accompanying this file. This file is distributed on an "AS IS"    */
11
+/* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the    */
12
+/* License for the specific language governing permissions and limitations under the License. */
13
+/**********************************************************************************************/
14
+
15
+#ifndef LIBCAPTION_XDS_H
16
+#define LIBCAPTION_XDS_H
17
+
18
+#include <stddef.h>
19
+#include <inttypes.h>
20
+
21
+typedef struct {
22
+    int state;
23
+    uint8_t class;
24
+    uint8_t type;
25
+    uint32_t size;
26
+    uint8_t content[32];
27
+    uint8_t checksum;
28
+} xds_t;
29
+
30
+void xds_init (xds_t* xds);
31
+int xds_decode (xds_t* xds, uint16_t cc);
32
+
33
+#endif
34
obs-studio-0.17.0.tar.xz/deps/libcaption/examples Added
2
 
1
+(directory)
2
obs-studio-0.17.0.tar.xz/deps/libcaption/examples/add_captions.sh Added
31
 
1
@@ -0,0 +1,29 @@
2
+#!/usr/bin/env bash
3
+
4
+if [  $# -lt 2 ]
5
+then
6
+    echo "Need at least 2 arguments."
7
+    echo "$0 InputVideo InputSRT [OutputFilename]"
8
+    exit 1
9
+fi
10
+
11
+VIDEO=$1
12
+SRT=$2
13
+
14
+if [ -z "$3" ]
15
+then
16
+    OUTFILE="out.flv"
17
+else
18
+    OUTFILE="$3"
19
+fi
20
+
21
+echo "Video=$VIDEO"
22
+echo "Captions=$SRT"
23
+echo "Outfile=$OUTFILE"
24
+
25
+# ffmpeg -i $VIDEO -acodec copy -vcodec copy -f flv - | ./flv+srt - $SRT - | ffmpeg -i - -acodec copy -vcodec copy $OUTFILE
26
+ffmpeg -i $VIDEO -threads 0 -vcodec libx264 -profile:v main -preset:v medium \
27
+-r 30 -g 60 -keyint_min 60 -sc_threshold 0 -b:v 4000k -maxrate 4000k \
28
+-bufsize 4000k -filter:v scale="trunc(oh*a/2)*2:720" \
29
+-sws_flags lanczos+accurate_rnd -strict -2 -acodec aac -b:a 96k -ar 48000 -ac 2 \
30
+-f flv - | ./flv+srt - $SRT - | ffmpeg -i - -acodec copy -vcodec copy -y $OUTFILE
31
obs-studio-0.17.0.tar.xz/deps/libcaption/examples/captioner.c Added
119
 
1
@@ -0,0 +1,117 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#include <stdlib.h>
26
+#include <unistd.h>
27
+#include <fcntl.h>
28
+#include <errno.h>
29
+#include <linux/input.h>
30
+#include <string.h>
31
+#include <stdio.h>
32
+#include "caption.h"
33
+#include "flv.h"
34
+
35
+char charcode[] = {
36
+    0,   0, '1', '2', '3', '4', '5', '6',  '7', '8', '9',  '0', '-', '=',   0,   0,
37
+    'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',  'O', 'P', '[',  ']','\n',   0, 'A', 'S',
38
+    'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', '\'', '`',   0, '\\', 'Z', 'X', 'C', 'V',
39
+    'B', 'N', 'M', ',', '.', '/',   0, '*',    0, ' ',   0,    0,   0,   0,   0,   0,
40
+};
41
+
42
+int data_ready (int fd)
43
+{
44
+    fd_set set;
45
+    struct timeval timeout = {0,0};
46
+    FD_ZERO (&set);
47
+    FD_SET (fd,&set);
48
+    int cnt = select (fd+1, &set, 0, 0, &timeout);
49
+    FD_ZERO (&set);
50
+    return (0 < cnt);
51
+}
52
+
53
+#define MAX_CAP_LENGTH (SCREEN_ROWS*SCREEN_COLS)
54
+int main (int argc, char** argv)
55
+{
56
+    int fd;
57
+    ssize_t n;
58
+    flvtag_t tag;
59
+    struct input_event ev;
60
+    int has_audio, has_video;
61
+    const char* dev = argv[1];
62
+    char text[MAX_CAP_LENGTH+1];
63
+    memset (text,0,MAX_CAP_LENGTH+1);
64
+
65
+    FILE* flv = flv_open_read ("-");
66
+    FILE* out = flv_open_write ("-");
67
+    fd = open (dev, O_RDONLY);
68
+
69
+    if (fd == -1) {
70
+        fprintf (stderr, "Cannot open %s: %s.\n", dev, strerror (errno));
71
+        return EXIT_FAILURE;
72
+    }
73
+
74
+    if (!flv_read_header (flv,&has_audio,&has_video)) {
75
+        fprintf (stderr,"%s is not an flv file\n", argv[1]);
76
+        return EXIT_FAILURE;
77
+    }
78
+
79
+    if (!flv_write_header (out,has_audio,has_video)) {
80
+        return EXIT_FAILURE;
81
+    }
82
+
83
+    flvtag_init (&tag);
84
+
85
+    while (flv_read_tag (flv,&tag)) {
86
+        if (flvtag_avcpackettype_nalu == flvtag_avcpackettype (&tag)) {
87
+            if (data_ready (fd)) {
88
+                n = read (fd, &ev, sizeof ev);
89
+
90
+                if (n == (ssize_t)-1) {
91
+                    if (errno == EINTR) {
92
+                        continue;
93
+                    } else {
94
+                        break;
95
+                    }
96
+                } else if (n != sizeof ev) {
97
+                    errno = EIO;
98
+                    break;
99
+                }
100
+
101
+                int len = strlen (text);
102
+                char c = (EV_KEY == ev.type && 1 == ev.value && ev.code < 64) ? charcode[ev.code] : 0;
103
+
104
+                if (0 < len && '\n' == c) {
105
+                    fprintf (stderr,"='%s'\n", text);
106
+                    flvtag_addcaption (&tag, text);
107
+                    memset (text,0,MAX_CAP_LENGTH+1);
108
+                } else if (0 != c && len < MAX_CAP_LENGTH) {
109
+                    text[len] = c;
110
+                }
111
+            }
112
+        }
113
+
114
+        flv_write_tag (out,&tag);
115
+    }
116
+
117
+    return EXIT_SUCCESS;
118
+}
119
obs-studio-0.17.0.tar.xz/deps/libcaption/examples/flv+scc.c Added
25
 
1
@@ -0,0 +1,23 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
obs-studio-0.17.0.tar.xz/deps/libcaption/examples/flv+srt.c Added
98
 
1
@@ -0,0 +1,96 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#include <stdio.h>
26
+#include <stdlib.h>
27
+#include <string.h>
28
+#include "srt.h"
29
+#include "flv.h"
30
+#include "avc.h"
31
+// #include "sei.h"
32
+
33
+#define MAX_SRT_SIZE (10*1024*1024)
34
+#define MAX_READ_SIZE 4096
35
+
36
+srt_t* srt_from_file (const char* path)
37
+{
38
+    srt_t* head = 0;
39
+    size_t read, totl = 0;
40
+    FILE* file = fopen (path,"r");
41
+
42
+    if (file) {
43
+        char* srt_data = malloc (MAX_SRT_SIZE);
44
+        size_t srt_size = 0;
45
+        size_t size = MAX_SRT_SIZE;
46
+        char* data = srt_data;
47
+
48
+        while (0 < (read = fread (data,1,size,file))) {
49
+            totl += read; data += read; size -= read; srt_size += read;
50
+        }
51
+
52
+        head = srt_parse (srt_data,srt_size);
53
+        free (srt_data);
54
+    }
55
+
56
+    return head;
57
+}
58
+
59
+int main (int argc, char** argv)
60
+{
61
+    flvtag_t tag;
62
+    FILE* flv = flv_open_read (argv[1]);
63
+    FILE* out = flv_open_write (argv[3]);
64
+
65
+    int has_audio, has_video;
66
+    flvtag_init (&tag);
67
+
68
+    if (!flv_read_header (flv,&has_audio,&has_video)) {
69
+        fprintf (stderr,"%s is not an flv file\n", argv[1]);
70
+        return EXIT_FAILURE;
71
+    }
72
+
73
+    srt_t* head = srt_from_file (argv[2]);
74
+    srt_t* srt = head;
75
+
76
+    if (! head) {
77
+        fprintf (stderr,"%s is not an srt file\n", argv[2]);
78
+        return EXIT_FAILURE;
79
+    }
80
+
81
+    flv_write_header (out,has_audio,has_video);
82
+
83
+    while (flv_read_tag (flv,&tag)) {
84
+        // TODO handle B freame!
85
+        if (srt && flvtag_pts_seconds (&tag) >= srt->timestamp && flvtag_avcpackettype_nalu == flvtag_avcpackettype (&tag)) {
86
+            fprintf (stderr,"%f: %s\n", srt->timestamp, srt_data (srt));
87
+            flvtag_addcaption (&tag, srt_data (srt));
88
+            srt = srt->next;
89
+        }
90
+
91
+        flv_write_tag (out,&tag);
92
+        // Write tag out here
93
+    }
94
+
95
+    srt_free (head);
96
+    return EXIT_SUCCESS;
97
+}
98
obs-studio-0.17.0.tar.xz/deps/libcaption/examples/flv.c Added
385
 
1
@@ -0,0 +1,383 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#include "flv.h"
26
+#include <stdlib.h>
27
+#include <string.h>
28
+
29
+void flvtag_init (flvtag_t* tag)
30
+{
31
+    memset (tag,0,sizeof (flvtag_t));
32
+}
33
+
34
+void flvtag_free (flvtag_t* tag)
35
+{
36
+    if (tag->data) {
37
+        free (tag->data);
38
+    }
39
+
40
+    flvtag_init (tag);
41
+}
42
+
43
+int flvtag_reserve (flvtag_t* tag, uint32_t size)
44
+{
45
+    size += FLV_TAG_HEADER_SIZE + FLV_TAG_FOOTER_SIZE;
46
+
47
+    if (size > tag->aloc) {
48
+        tag->data = realloc (tag->data,size);
49
+        tag->aloc = size;
50
+    }
51
+
52
+    return 1;
53
+}
54
+
55
+FILE* flv_open_read (const char* flv)
56
+{
57
+    if (0 == flv || 0 == strcmp ("-",flv)) {
58
+        return stdin;
59
+    }
60
+
61
+    return fopen (flv,"rb");
62
+}
63
+
64
+FILE* flv_open_write (const char* flv)
65
+{
66
+    if (0 == flv || 0 == strcmp ("-",flv)) {
67
+        return stdout;
68
+    }
69
+
70
+    return fopen (flv,"wb");
71
+}
72
+
73
+FILE* flv_close (FILE* flv)
74
+{
75
+    fclose (flv);
76
+    return 0;
77
+}
78
+
79
+int flv_read_header (FILE* flv, int* has_audio, int* has_video)
80
+{
81
+    uint8_t h[FLV_HEADER_SIZE];
82
+
83
+    if (FLV_HEADER_SIZE != fread (&h[0],1,FLV_HEADER_SIZE,flv)) {
84
+        return 0;
85
+    }
86
+
87
+    if ('F' != h[0] || 'L' != h[1] || 'V' != h[2]) {
88
+        return 0;
89
+    }
90
+
91
+    (*has_audio) = h[4]&0x04;
92
+    (*has_video) = h[4]&0x01;
93
+    return 1;
94
+}
95
+
96
+int flv_write_header (FILE* flv, int has_audio, int has_video)
97
+{
98
+    uint8_t h[FLV_HEADER_SIZE] = {'F', 'L', 'V', 1, (has_audio?0x04:0x00) | (has_video?0x01:0x00), 0, 0, 0, 9, 0, 0, 0, 0 };
99
+    return FLV_HEADER_SIZE == fwrite (&h[0],1,FLV_HEADER_SIZE,flv);
100
+}
101
+
102
+int flv_read_tag (FILE* flv, flvtag_t* tag)
103
+{
104
+    uint32_t size;
105
+    uint8_t h[FLV_TAG_HEADER_SIZE];
106
+
107
+    if (FLV_TAG_HEADER_SIZE != fread (&h[0],1,FLV_TAG_HEADER_SIZE,flv)) {
108
+        return 0;
109
+    }
110
+
111
+    size = ( (h[1]<<16) | (h[2]<<8) |h[3]);
112
+    flvtag_reserve (tag, size);
113
+    // copy header to buffer
114
+    memcpy (tag->data,&h[0],FLV_TAG_HEADER_SIZE);
115
+
116
+    if (size+FLV_TAG_FOOTER_SIZE != fread (&tag->data[FLV_TAG_HEADER_SIZE],1,size+FLV_TAG_FOOTER_SIZE,flv)) {
117
+        return 0;
118
+    }
119
+
120
+    return 1;
121
+}
122
+
123
+int flv_write_tag (FILE* flv, flvtag_t* tag)
124
+{
125
+    size_t size = flvtag_raw_size (tag);
126
+    return size == fwrite (flvtag_raw_data (tag),1,size,flv);
127
+}
128
+////////////////////////////////////////////////////////////////////////////////
129
+size_t flvtag_header_size (flvtag_t* tag)
130
+{
131
+    switch (flvtag_type (tag)) {
132
+    case flvtag_type_audio:
133
+        return FLV_TAG_HEADER_SIZE + (flvtag_soundformat_aac != flvtag_soundformat (tag) ? 1 : 2);
134
+
135
+    case flvtag_type_video:
136
+        // CommandFrame does not have a compositionTime
137
+        return FLV_TAG_HEADER_SIZE + (flvtag_codecid_avc != flvtag_codecid (tag) ? 1 : (flvtag_frametype_commandframe != flvtag_frametype (tag) ? 5 : 2));
138
+
139
+    default:
140
+        return FLV_TAG_HEADER_SIZE;
141
+    }
142
+}
143
+
144
+size_t flvtag_payload_size (flvtag_t* tag)
145
+{
146
+    return FLV_TAG_HEADER_SIZE + flvtag_size (tag) - flvtag_header_size (tag);
147
+}
148
+
149
+uint8_t* flvtag_payload_data (flvtag_t* tag)
150
+{
151
+    size_t payload_offset = flvtag_header_size (tag);
152
+    return &tag->data[payload_offset];
153
+}
154
+////////////////////////////////////////////////////////////////////////////////
155
+int flvtag_updatesize (flvtag_t* tag, uint32_t size)
156
+{
157
+    tag->data[1] = size>>16; // DataSize
158
+    tag->data[2] = size>>8; // DataSize
159
+    tag->data[3] = size>>0; // DataSize
160
+    size += 11;
161
+    tag->data[size+0] = size>>24; // PrevTagSize
162
+    tag->data[size+1] = size>>16; // PrevTagSize
163
+    tag->data[size+2] = size>>8; // PrevTagSize
164
+    tag->data[size+3] = size>>0; // PrevTagSize
165
+    return 1;
166
+}
167
+
168
+#define FLVTAG_PREALOC 2048
169
+int flvtag_initavc (flvtag_t* tag, uint32_t dts, int32_t cts, flvtag_frametype_t type)
170
+{
171
+    flvtag_init (tag);
172
+    flvtag_reserve (tag,5+FLVTAG_PREALOC);
173
+    tag->data[0] = flvtag_type_video;
174
+    tag->data[4] = dts>>16;
175
+    tag->data[5] = dts>>8;
176
+    tag->data[6] = dts>>0;
177
+    tag->data[7] = dts>>24;
178
+    tag->data[8] = 0; // StreamID
179
+    tag->data[9] = 0; // StreamID
180
+    tag->data[10] = 0; // StreamID
181
+    // VideoTagHeader
182
+    tag->data[11] = ( (type<<4) %0xF0) |0x07; // CodecId
183
+    tag->data[12] = 0x01; // AVC NALU
184
+    tag->data[13] = cts>>16;
185
+    tag->data[14] = cts>>8;
186
+    tag->data[15] = cts>>0;
187
+    flvtag_updatesize (tag,5);
188
+    return 1;
189
+}
190
+
191
+int flvtag_initamf (flvtag_t* tag, uint32_t dts)
192
+{
193
+    flvtag_init (tag);
194
+    flvtag_reserve (tag,FLVTAG_PREALOC);
195
+    tag->data[0] = flvtag_type_scriptdata;
196
+    tag->data[4] = dts>>16;
197
+    tag->data[5] = dts>>8;
198
+    tag->data[6] = dts>>0;
199
+    tag->data[7] = dts>>24;
200
+    tag->data[8] = 0; // StreamID
201
+    tag->data[9] = 0; // StreamID
202
+    tag->data[10] = 0; // StreamID
203
+    flvtag_updatesize (tag,0);
204
+    return 1;
205
+}
206
+
207
+// shamelessly taken from libtomcrypt, an public domain project
208
+static void base64_encode (const unsigned char* in,  unsigned long inlen, unsigned char* out, unsigned long* outlen)
209
+{
210
+    static const char* codes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
211
+    unsigned long i, len2, leven;
212
+    unsigned char* p;
213
+
214
+    /* valid output size ? */
215
+    len2 = 4 * ( (inlen + 2) / 3);
216
+
217
+    if (*outlen < len2 + 1) {
218
+        *outlen = len2 + 1;
219
+        fprintf (stderr,"\n\nHERE\n\n");
220
+        return;
221
+    }
222
+
223
+    p = out;
224
+    leven = 3* (inlen / 3);
225
+
226
+    for (i = 0; i < leven; i += 3) {
227
+        *p++ = codes[ (in[0] >> 2) & 0x3F];
228
+        *p++ = codes[ ( ( (in[0] & 3) << 4) + (in[1] >> 4)) & 0x3F];
229
+        *p++ = codes[ ( ( (in[1] & 0xf) << 2) + (in[2] >> 6)) & 0x3F];
230
+        *p++ = codes[in[2] & 0x3F];
231
+        in += 3;
232
+    }
233
+
234
+    if (i < inlen) {
235
+        unsigned a = in[0];
236
+        unsigned b = (i+1 < inlen) ? in[1] : 0;
237
+
238
+        *p++ = codes[ (a >> 2) & 0x3F];
239
+        *p++ = codes[ ( ( (a & 3) << 4) + (b >> 4)) & 0x3F];
240
+        *p++ = (i+1 < inlen) ? codes[ ( ( (b & 0xf) << 2)) & 0x3F] : '=';
241
+        *p++ = '=';
242
+    }
243
+
244
+    /* return ok */
245
+    *outlen = p - out;
246
+}
247
+
248
+const char onCaptionInfo708[] = { 0x02,0x00,0x0D, 'o','n','C','a','p','t','i','o','n','I','n','f','o',
249
+                                  0x08, 0x00, 0x00, 0x00, 0x02,
250
+                                  0x00, 0x04, 't','y','p','e',
251
+                                  0x02, 0x00, 0x03, '7','0','8',
252
+                                  0x00, 0x04, 'd','a','t','a',
253
+                                  0x02, 0x00,0x00
254
+                                };
255
+
256
+int flvtag_amfcaption_708 (flvtag_t* tag, uint32_t timestamp, sei_message_t* msg)
257
+{
258
+    flvtag_initamf (tag,timestamp);
259
+    unsigned long size = 1 + (4 * ( (sei_message_size (msg) + 2) / 3));
260
+    flvtag_reserve (tag, sizeof (onCaptionInfo708) + size + 3);
261
+    memcpy (flvtag_payload_data (tag),onCaptionInfo708,sizeof (onCaptionInfo708));
262
+    uint8_t* data = flvtag_payload_data (tag) + sizeof (onCaptionInfo708);
263
+    base64_encode (sei_message_data (msg), sei_message_size (msg), data, &size);
264
+
265
+    // Update the size of the base64 string
266
+    data[-2] = size >> 8;
267
+    data[-1] = size >> 0;
268
+    // write the last array element
269
+    data[size+0] = 0x00;
270
+    data[size+1] = 0x00;
271
+    data[size+2] = 0x09;
272
+    flvtag_updatesize (tag, sizeof (onCaptionInfo708) + size + 3);
273
+
274
+    return 1;
275
+}
276
+
277
+const char onCaptionInfoUTF8[] = { 0x02,0x00,0x0D, 'o','n','C','a','p','t','i','o','n','I','n','f','o',
278
+                                   0x08, 0x00, 0x00, 0x00, 0x02,
279
+                                   0x00, 0x04, 't','y','p','e',
280
+                                   0x02, 0x00, 0x04, 'U','T','F','8',
281
+                                   0x00, 0x04, 'd','a','t','a',
282
+                                   0x02, 0x00,0x00
283
+                                 };
284
+
285
+#define MAX_AMF_STRING 65636
286
+int flvtag_amfcaption_utf8 (flvtag_t* tag, uint32_t timestamp, const utf8_char_t* text)
287
+{
288
+    flvtag_initamf (tag,timestamp);
289
+    unsigned long size = strlen (text);
290
+
291
+    if (MAX_AMF_STRING < size) {
292
+        size = MAX_AMF_STRING;
293
+    }
294
+
295
+    flvtag_reserve (tag, sizeof (onCaptionInfoUTF8) + size + 3);
296
+    memcpy (flvtag_payload_data (tag),onCaptionInfoUTF8,sizeof (onCaptionInfoUTF8));
297
+    uint8_t* data = flvtag_payload_data (tag) + sizeof (onCaptionInfo708);
298
+    memcpy (data,text,size);
299
+    // Update the size of the string
300
+    data[-2] = size >> 8;
301
+    data[-1] = size >> 0;
302
+    // write the last array element
303
+    data[size+0] = 0x00;
304
+    data[size+1] = 0x00;
305
+    data[size+2] = 0x09;
306
+    flvtag_updatesize (tag, sizeof (onCaptionInfoUTF8) + size + 3);
307
+
308
+    return 1;
309
+}
310
+
311
+#define LENGTH_SIZE 4
312
+
313
+int flvtag_avcwritenal (flvtag_t* tag, uint8_t* data, size_t size)
314
+{
315
+    uint32_t flvsize = flvtag_size (tag);
316
+    flvtag_reserve (tag,flvsize+LENGTH_SIZE+size);
317
+    uint8_t* payload = tag->data + FLV_TAG_HEADER_SIZE + flvsize;
318
+    payload[0] = size>>24; // nalu size
319
+    payload[1] = size>>16;
320
+    payload[2] = size>>8;
321
+    payload[3] = size>>0;
322
+    memcpy (&payload[LENGTH_SIZE],data,size);
323
+    flvtag_updatesize (tag,flvsize+LENGTH_SIZE+size);
324
+
325
+    return 1;
326
+}
327
+
328
+int flvtag_addcaption (flvtag_t* tag, const utf8_char_t* text)
329
+{
330
+    if (flvtag_avcpackettype_nalu != flvtag_avcpackettype (tag)) {
331
+        return 0;
332
+    }
333
+
334
+    sei_t sei;
335
+    caption_frame_t frame;
336
+
337
+    sei_init (&sei);
338
+    caption_frame_init (&frame);
339
+    caption_frame_from_text (&frame, text);
340
+    sei_from_caption_frame (&sei, &frame);
341
+
342
+    uint8_t* sei_data = malloc (sei_render_size (&sei));
343
+    size_t sei_size = sei_render (&sei, sei_data);
344
+
345
+    // rewrite tag
346
+    flvtag_t new_tag;
347
+    flvtag_initavc (&new_tag, flvtag_dts (tag), flvtag_cts (tag), flvtag_frametype (tag));
348
+    uint8_t* data = flvtag_payload_data (tag);
349
+    ssize_t  size = flvtag_payload_size (tag);
350
+
351
+    while (0<size) {
352
+        uint8_t*  nalu_data = &data[LENGTH_SIZE];
353
+        uint8_t   nalu_type = nalu_data[0]&0x1F;
354
+        uint32_t  nalu_size = (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | data[3];
355
+        data += LENGTH_SIZE + nalu_size;
356
+        size -= LENGTH_SIZE + nalu_size;
357
+
358
+        if (0 < sei_size && 7 != nalu_type && 8 != nalu_type && 9 != nalu_type ) {
359
+            // fprintf (stderr,"Wrote SEI %d '%d'\n\n", sei_size, sei_data[3]);
360
+            flvtag_avcwritenal (&new_tag,sei_data,sei_size);
361
+            sei_size = 0;
362
+        }
363
+
364
+        flvtag_avcwritenal (&new_tag,nalu_data,nalu_size);
365
+    }
366
+
367
+    // On the off chance we have an empty frame,
368
+    // We still wish to append the sei
369
+    if (0<sei_size) {
370
+        // fprintf (stderr,"Wrote SEI %d\n\n", sei_size);
371
+        flvtag_avcwritenal (&new_tag,sei_data,sei_size);
372
+        sei_size = 0;
373
+    }
374
+
375
+    if (sei_data) {
376
+        free (sei_data);
377
+    }
378
+
379
+    free (tag->data);
380
+    sei_free (&sei);
381
+    tag->data = new_tag.data;
382
+    tag->aloc = new_tag.aloc;
383
+    return 1;
384
+}
385
obs-studio-0.17.0.tar.xz/deps/libcaption/examples/flv.h Added
144
 
1
@@ -0,0 +1,142 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#ifndef LIBCAPTION_FLV_H
26
+#define LIBCAPTION_FLV_H
27
+
28
+#include <stdio.h>
29
+#include <stddef.h>
30
+#include <inttypes.h>
31
+#define FLV_HEADER_SIZE     13
32
+#define FLV_FOOTER_SIZE      4
33
+#define FLV_TAG_HEADER_SIZE 11
34
+#define FLV_TAG_FOOTER_SIZE  4
35
+////////////////////////////////////////////////////////////////////////////////
36
+#include "avc.h"
37
+////////////////////////////////////////////////////////////////////////////////
38
+typedef struct {
39
+    uint8_t* data;
40
+    size_t   aloc;
41
+} flvtag_t;
42
+
43
+void flvtag_init (flvtag_t* tag);
44
+void flvtag_free (flvtag_t* tag);
45
+void flvtag_swap (flvtag_t* tag1, flvtag_t* tag2);
46
+////////////////////////////////////////////////////////////////////////////////
47
+typedef enum {
48
+    flvtag_type_audio      = 0x08,
49
+    flvtag_type_video      = 0x09,
50
+    flvtag_type_scriptdata = 0x12,
51
+} flvtag_type_t;
52
+
53
+static inline flvtag_type_t flvtag_type (flvtag_t* tag) { return (flvtag_type_t) tag->data[0]&0x1F; }
54
+////////////////////////////////////////////////////////////////////////////////
55
+typedef enum {
56
+    flvtag_soundformat_unknown                            = -1,
57
+    flvtag_soundformat_linearpcmplatformendian            =  0,
58
+    flvtag_soundformat_adpcm                              =  1,
59
+    flvtag_soundformat_mp3                                =  2,
60
+    flvtag_soundformat_linearpcmlittleendian              =  3,
61
+    flvtag_soundformat_nellymoser_16khzmono               =  4,
62
+    flvtag_soundformat_nellymoser_8khzmono                =  5,
63
+    flvtag_soundformat_nellymoser                         =  6,
64
+    flvtag_soundformat_g711alawlogarithmicpcm             =  7,
65
+    flvtag_soundformat_g711mulawlogarithmicpcm            =  8,
66
+    flvtag_soundformat_reserved                           =  9,
67
+    flvtag_soundformat_aac                                = 10,
68
+    flvtag_soundformat_speex                              = 11,
69
+    flvtag_soundformat_mp3_8khz                           = 14,
70
+    flvtag_soundformat_devicespecificsound                = 15
71
+} flvtag_soundformat_t;
72
+
73
+static inline flvtag_soundformat_t flvtag_soundformat (flvtag_t* tag) { return (flvtag_type_audio!=flvtag_type (tag)) ?flvtag_soundformat_unknown: (flvtag_soundformat_t) (tag->data[0]>>4) &0x0F; }
74
+////////////////////////////////////////////////////////////////////////////////
75
+typedef enum {
76
+    flvtag_codecid_unknown                = -1,
77
+    flvtag_codecid_sorensonh263           =  2,
78
+    flvtag_codecid_screenvideo            =  3,
79
+    flvtag_codecid_on2vp6                 =  4,
80
+    flvtag_codecid_on2vp6withalphachannel =  5,
81
+    flvtag_codecid_screenvideoversion2    =  6,
82
+    flvtag_codecid_avc                    =  7
83
+} flvtag_codecid_t;
84
+
85
+static inline flvtag_codecid_t flvtag_codecid (flvtag_t* tag) { return (flvtag_type_video!=flvtag_type (tag)) ? (flvtag_codecid_unknown) : (tag->data[11]&0x0F); }
86
+////////////////////////////////////////////////////////////////////////////////
87
+typedef enum {
88
+    flvtag_frametype_unknown              = -1,
89
+    flvtag_frametype_keyframe             =  1,
90
+    flvtag_frametype_interframe           =  2,
91
+    flvtag_frametype_disposableinterframe =  3,
92
+    flvtag_frametype_generatedkeyframe    =  4,
93
+    flvtag_frametype_commandframe         =  5
94
+} flvtag_frametype_t;
95
+
96
+static inline flvtag_frametype_t flvtag_frametype (flvtag_t* tag) { return (flvtag_type_video!=flvtag_type (tag)) ?flvtag_frametype_keyframe: ( (tag->data[11]>>4) &0x0F); }
97
+////////////////////////////////////////////////////////////////////////////////
98
+typedef enum {
99
+    flvtag_avcpackettype_unknown        = -1,
100
+    flvtag_avcpackettype_sequenceheader =  0,
101
+    flvtag_avcpackettype_nalu           =  1,
102
+    flvtag_avcpackettype_endofsequence  =  2
103
+} flvtag_avcpackettype_t;
104
+
105
+static inline flvtag_avcpackettype_t flvtag_avcpackettype (flvtag_t* tag) { return (flvtag_codecid_avc!=flvtag_codecid (tag)) ?flvtag_avcpackettype_unknown:tag->data[12]; }
106
+////////////////////////////////////////////////////////////////////////////////
107
+static inline size_t   flvtag_size (flvtag_t* tag) { return (tag->data[1]<<16) | (tag->data[2]<<8) | tag->data[3]; }
108
+static inline uint32_t flvtag_timestamp (flvtag_t* tag) { return (tag->data[7]<<24) | (tag->data[4]<<16) | (tag->data[5]<<8) | tag->data[6]; }
109
+static inline uint32_t flvtag_dts (flvtag_t* tag) { return flvtag_timestamp (tag); }
110
+static inline uint32_t flvtag_cts (flvtag_t* tag) { return (flvtag_avcpackettype_nalu!=flvtag_avcpackettype (tag)) ?0: (tag->data[13]<<16) | (tag->data[14]<<8) |tag->data[15]; }
111
+static inline uint32_t flvtag_pts (flvtag_t* tag) { return flvtag_dts (tag)+flvtag_cts (tag); }
112
+static inline double flvtag_dts_seconds (flvtag_t* tag) { return flvtag_dts (tag) / 1000.0; }
113
+static inline double flvtag_cts_seconds (flvtag_t* tag) { return flvtag_cts (tag) / 1000.0; }
114
+static inline double flvtag_pts_seconds (flvtag_t* tag) { return flvtag_pts (tag) / 1000.0; }
115
+////////////////////////////////////////////////////////////////////////////////
116
+size_t flvtag_header_size (flvtag_t* tag);
117
+size_t flvtag_payload_size (flvtag_t* tag);
118
+uint8_t* flvtag_payload_data (flvtag_t* tag);
119
+////////////////////////////////////////////////////////////////////////////////
120
+FILE* flv_open_read (const char* flv);
121
+FILE* flv_open_write (const char* flv);
122
+FILE* flv_close (FILE* flv);
123
+////////////////////////////////////////////////////////////////////////////////
124
+static inline const uint8_t* flvtag_raw_data (flvtag_t* tag) { return tag->data; }
125
+static inline const size_t flvtag_raw_size (flvtag_t* tag) { return flvtag_size (tag)+FLV_TAG_HEADER_SIZE+FLV_TAG_FOOTER_SIZE; }
126
+////////////////////////////////////////////////////////////////////////////////
127
+int flv_read_tag (FILE* flv, flvtag_t* tag);
128
+int flv_write_tag (FILE* flv, flvtag_t* tag);
129
+int flv_read_header (FILE* flv, int* has_audio, int* has_video);
130
+int flv_write_header (FILE* flv, int has_audio, int has_video);
131
+////////////////////////////////////////////////////////////////////////////////
132
+// If the tage has more that on sei message, they will be combined into one
133
+sei_t* flv_read_sei (FILE* flv, flvtag_t* tag);
134
+////////////////////////////////////////////////////////////////////////////////
135
+int flvtag_initavc (flvtag_t* tag, uint32_t dts, int32_t cts, flvtag_frametype_t type);
136
+int flvtag_avcwritenal (flvtag_t* tag, uint8_t* data, size_t size);
137
+int flvtag_addcaption (flvtag_t* tag, const utf8_char_t* text);
138
+////////////////////////////////////////////////////////////////////////////////
139
+int flvtag_amfcaption_708 (flvtag_t* tag, uint32_t timestamp, sei_message_t* msg);
140
+////////////////////////////////////////////////////////////////////////////////
141
+// This method is expermental, and not currently available on Twitch
142
+int flvtag_amfcaption_utf8 (flvtag_t* tag, uint32_t timestamp, const utf8_char_t* text);
143
+#endif
144
obs-studio-0.17.0.tar.xz/deps/libcaption/examples/flv2srt.c Added
94
 
1
@@ -0,0 +1,92 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#include "flv.h"
26
+#include "srt.h"
27
+#include "avc.h"
28
+
29
+#define LENGTH_SIZE 4
30
+int main (int argc, char** argv)
31
+{
32
+    const char* path = argv[1];
33
+
34
+    sei_t sei;
35
+    flvtag_t tag;
36
+    srt_t* srt = 0, *head = 0;
37
+    int i, has_audio, has_video;
38
+    caption_frame_t frame;
39
+
40
+    flvtag_init (&tag);
41
+    caption_frame_init (&frame);
42
+
43
+    FILE* flv = flv_open_read (path);
44
+
45
+    if (!flv_read_header (flv,&has_audio,&has_video)) {
46
+        fprintf (stderr,"'%s' Not an flv file\n", path);
47
+    } else {
48
+        fprintf (stderr,"Reading from '%s'\n", path);
49
+    }
50
+
51
+    while (flv_read_tag (flv,&tag)) {
52
+        if (flvtag_avcpackettype_nalu == flvtag_avcpackettype (&tag)) {
53
+            ssize_t  size = flvtag_payload_size (&tag);
54
+            uint8_t* data = flvtag_payload_data (&tag);
55
+
56
+            while (0<size) {
57
+                ssize_t  nalu_size = (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | data[3];
58
+                uint8_t* nalu_data = &data[4];
59
+                uint8_t  nalu_type = nalu_data[0]&0x1F;
60
+                data += nalu_size + LENGTH_SIZE;
61
+                size -= nalu_size + LENGTH_SIZE;
62
+
63
+                if (6 == nalu_type) {
64
+                    sei_init (&sei);
65
+                    sei_parse_nalu (&sei, nalu_data, nalu_size, flvtag_dts (&tag), flvtag_cts (&tag));
66
+
67
+                    cea708_t cea708;
68
+                    sei_message_t* msg;
69
+                    cea708_init (&cea708);
70
+
71
+                    // for (msg = sei_message_head (&sei) ; msg ; msg = sei_message_next (msg)) {
72
+                    //     if (sei_type_user_data_registered_itu_t_t35 == sei_message_type (msg)) {
73
+                    //         cea708_parse (sei_message_data (msg), sei_message_size (msg), &cea708);
74
+                    //         cea708_dump (&cea708);
75
+                    //     }
76
+                    // }
77
+
78
+                    // sei_dump(&sei);
79
+                    sei_to_caption_frame (&sei,&frame);
80
+                    sei_free (&sei);
81
+
82
+                    // caption_frame_dump (&frame);
83
+                    srt = srt_from_caption_frame (&frame,srt,&head);
84
+                }
85
+            }
86
+        }
87
+    }
88
+
89
+    srt_dump (head);
90
+    srt_free (head);
91
+
92
+    return 1;
93
+}
94
obs-studio-0.17.0.tar.xz/deps/libcaption/examples/party.c Added
124
 
1
@@ -0,0 +1,122 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#include <stdio.h>
26
+#include <stdlib.h>
27
+#include <string.h>
28
+#include "flv.h"
29
+#include "avc.h"
30
+
31
+#define CAPTION_METHOD_SEI_708  0 // embedded 708
32
+#define CAPTION_METHOD_AMF_708  1 // onCaptionInfo type = 708
33
+#define CAPTION_METHOD_AMF_UTF8 2 // onCaptionInfo type = utf8
34
+#define CAPTION_METHOD CAPTION_METHOD_SEI_708
35
+
36
+void get_dudes (char* str)
37
+{
38
+    sprintf (str, " %s%s %s(-_-)%s %s(-_-)%s.%s(-_-)%s %s%s", EIA608_CHAR_EIGHTH_NOTE, EIA608_CHAR_EIGHTH_NOTE,
39
+             ! (rand() % 2) ? EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_RIGHT : EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_RIGHT,
40
+             ! (rand() % 2) ? EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_LEFT : EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_LEFT,
41
+             ! (rand() % 2) ? EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_RIGHT : EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_RIGHT,
42
+             ! (rand() % 2) ? EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_LEFT : EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_LEFT,
43
+             ! (rand() % 2) ? EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_RIGHT : EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_RIGHT,
44
+             ! (rand() % 2) ? EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_LEFT : EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_LEFT,
45
+             EIA608_CHAR_EIGHTH_NOTE, EIA608_CHAR_EIGHTH_NOTE);
46
+}
47
+
48
+void write_amfcaptions_708 (FILE* out, uint32_t timestamp, const char* text)
49
+{
50
+    sei_t sei;
51
+    flvtag_t tag;
52
+    sei_message_t* msg;
53
+    caption_frame_t frame;
54
+    sei_init (&sei);
55
+    flvtag_init (&tag);
56
+    caption_frame_init (&frame);
57
+    caption_frame_from_text (&frame, text);
58
+    sei_from_caption_frame (&sei, &frame);
59
+    // caption_frame_dump (&frame);
60
+
61
+    for (msg = sei_message_head (&sei); msg; msg=sei_message_next (msg),++timestamp) {
62
+        flvtag_amfcaption_708 (&tag,timestamp,msg);
63
+        flv_write_tag (out,&tag);
64
+    }
65
+
66
+    sei_free (&sei);
67
+    flvtag_free (&tag);
68
+}
69
+
70
+
71
+void write_amfcaptions_utf8 (FILE* out, uint32_t timestamp, const utf8_char_t* text)
72
+{
73
+    flvtag_t tag;
74
+    flvtag_init (&tag);
75
+    flvtag_amfcaption_utf8 (&tag,timestamp,text);
76
+    flv_write_tag (out,&tag);
77
+    flvtag_free (&tag);
78
+}
79
+
80
+int main (int argc, char** argv)
81
+{
82
+    flvtag_t tag;
83
+    uint32_t nextParty = 1000;
84
+    int has_audio, has_video;
85
+    FILE* flv = flv_open_read (argv[1]);
86
+    FILE* out = flv_open_write (argv[2]);
87
+    char partyDudes[64];
88
+
89
+    flvtag_init (&tag);
90
+
91
+    if (!flv_read_header (flv,&has_audio,&has_video)) {
92
+        fprintf (stderr,"%s is not an flv file\n", argv[1]);
93
+        return EXIT_FAILURE;
94
+    }
95
+
96
+    flv_write_header (out,has_audio,has_video);
97
+
98
+    while (flv_read_tag (flv,&tag)) {
99
+
100
+        if (flvtag_avcpackettype_nalu == flvtag_avcpackettype (&tag) && nextParty <= flvtag_timestamp (&tag)) {
101
+            get_dudes (partyDudes);
102
+
103
+            if (CAPTION_METHOD == CAPTION_METHOD_SEI_708) {
104
+                flvtag_addcaption (&tag, partyDudes);
105
+            } else if (CAPTION_METHOD == CAPTION_METHOD_AMF_708) {
106
+                write_amfcaptions_708 (out,nextParty,partyDudes);
107
+            } else if (CAPTION_METHOD == CAPTION_METHOD_AMF_708) {
108
+                write_amfcaptions_utf8 (out, nextParty, partyDudes);
109
+            } else {
110
+                fprintf (stderr,"Unknnow method\n");
111
+                return EXIT_FAILURE;
112
+
113
+            }
114
+
115
+            fprintf (stderr,"%d: %s\n",nextParty, partyDudes);
116
+            nextParty += 500; // party all the time
117
+        }
118
+
119
+        flv_write_tag (out,&tag);
120
+    }
121
+
122
+    return EXIT_SUCCESS;
123
+}
124
obs-studio-0.17.0.tar.xz/deps/libcaption/examples/rollup.c Added
97
 
1
@@ -0,0 +1,95 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#include <stdio.h>
26
+#include <stdlib.h>
27
+#include <string.h>
28
+#include "flv.h"
29
+#include "avc.h"
30
+#include "srt.h"
31
+#include "wonderland.h"
32
+
33
+#define SECONDS_PER_LINE 3.0
34
+srt_t* appennd_caption (const utf8_char_t* data, srt_t* prev, srt_t** head)
35
+{
36
+
37
+    int r, c, chan = 0;
38
+    ssize_t size = (ssize_t) strlen (data);
39
+    size_t char_count, char_length, line_length = 0, trimmed_length = 0;
40
+
41
+    for (r = 0 ; 0 < size && SCREEN_ROWS > r ; ++r) {
42
+        line_length = utf8_line_length (data);
43
+        trimmed_length = utf8_trimmed_length (data,line_length);
44
+        char_count = utf8_char_count (data,trimmed_length);
45
+
46
+        // If char_count is greater than one line can display, split it.
47
+        if (SCREEN_COLS < char_count) {
48
+            char_count = utf8_wrap_length (data,SCREEN_COLS);
49
+            line_length = utf8_string_length (data,char_count+1);
50
+        }
51
+
52
+        // fprintf (stderr,"%.*s\n", line_length, data);
53
+        prev = srt_new (data, line_length, prev ? prev->timestamp + SECONDS_PER_LINE : 0, prev, head);
54
+
55
+        data += line_length;
56
+        size -= (ssize_t) line_length;
57
+    }
58
+
59
+    return prev;
60
+}
61
+
62
+int main (int argc, char** argv)
63
+{
64
+    int i = 0;
65
+    flvtag_t tag;
66
+    srt_t* head = 0, *tail = 0;
67
+    int has_audio, has_video;
68
+    FILE* flv = flv_open_read (argv[1]);
69
+    FILE* out = flv_open_write (argv[2]);
70
+    flvtag_init (&tag);
71
+
72
+    for (i = 0 ; wonderland[i][0]; ++i) {
73
+        tail = appennd_caption (wonderland[i], tail, &head);
74
+    }
75
+
76
+
77
+    if (!flv_read_header (flv,&has_audio,&has_video)) {
78
+        fprintf (stderr,"%s is not an flv file\n", argv[1]);
79
+        return EXIT_FAILURE;
80
+    }
81
+
82
+    flv_write_header (out,has_audio,has_video);
83
+
84
+    while (flv_read_tag (flv,&tag)) {
85
+        if (head && flvtag_avcpackettype_nalu == flvtag_avcpackettype (&tag) && head->timestamp <= flvtag_pts_seconds (&tag)) {
86
+            fprintf (stderr,"%f %s\n", flvtag_pts_seconds (&tag), srt_data (head));
87
+            flvtag_addcaption (&tag, srt_data (head));
88
+            head = srt_free_head (head);
89
+        }
90
+
91
+
92
+        flv_write_tag (out,&tag);
93
+    }
94
+
95
+    return EXIT_SUCCESS;
96
+}
97
obs-studio-0.17.0.tar.xz/deps/libcaption/examples/rtmpspit.c Added
167
 
1
@@ -0,0 +1,165 @@
2
+#include "flv.h"
3
+#include <stdio.h>
4
+#include <unistd.h>
5
+#include <string.h>
6
+#include <stdlib.h>
7
+#include <sys/select.h>
8
+#include <librtmp/log.h>
9
+#include <librtmp/rtmp.h>
10
+
11
+
12
+int MyRTMP_Write (RTMP* r, const char* buf, int size)
13
+{
14
+    RTMPPacket* pkt = &r->m_write;
15
+    char* enc;
16
+    int s2 = size, ret, num;
17
+
18
+    pkt->m_nChannel = 0x04;   /* source channel */
19
+    pkt->m_nInfoField2 = r->m_stream_id;
20
+
21
+    while (s2) {
22
+        if (!pkt->m_nBytesRead) {
23
+            if (size < 11) {
24
+                /* FLV pkt too small */
25
+                return 0;
26
+            }
27
+
28
+            if (buf[0] == 'F' && buf[1] == 'L' && buf[2] == 'V') {
29
+                buf += 13;
30
+                s2 -= 13;
31
+            }
32
+
33
+            pkt->m_packetType = *buf++;
34
+            pkt->m_nBodySize = AMF_DecodeInt24 (buf);
35
+            buf += 3;
36
+            pkt->m_nTimeStamp = AMF_DecodeInt24 (buf);
37
+            buf += 3;
38
+            pkt->m_nTimeStamp |= *buf++ << 24;
39
+            buf += 3;
40
+            s2 -= 11;
41
+
42
+            if ( ( (pkt->m_packetType == RTMP_PACKET_TYPE_AUDIO
43
+                    || pkt->m_packetType == RTMP_PACKET_TYPE_VIDEO) &&
44
+                    !pkt->m_nTimeStamp) || pkt->m_packetType == RTMP_PACKET_TYPE_INFO) {
45
+                pkt->m_headerType = RTMP_PACKET_SIZE_LARGE;
46
+            } else {
47
+                pkt->m_headerType = RTMP_PACKET_SIZE_MEDIUM;
48
+            }
49
+
50
+            if (!RTMPPacket_Alloc (pkt, pkt->m_nBodySize)) {
51
+                RTMP_Log (RTMP_LOGDEBUG, "%s, failed to allocate packet", __FUNCTION__);
52
+                return FALSE;
53
+            }
54
+
55
+            enc = pkt->m_body;
56
+        } else {
57
+            enc = pkt->m_body + pkt->m_nBytesRead;
58
+        }
59
+
60
+        num = pkt->m_nBodySize - pkt->m_nBytesRead;
61
+
62
+        if (num > s2) {
63
+            num = s2;
64
+        }
65
+
66
+        memcpy (enc, buf, num);
67
+        pkt->m_nBytesRead += num;
68
+        s2 -= num;
69
+        buf += num;
70
+
71
+        if (pkt->m_nBytesRead == pkt->m_nBodySize) {
72
+            ret = RTMP_SendPacket (r, pkt, FALSE);
73
+            RTMPPacket_Free (pkt);
74
+            pkt->m_nBytesRead = 0;
75
+
76
+            if (!ret) {
77
+                return -1;
78
+            }
79
+
80
+            buf += 4;
81
+            s2 -= 4;
82
+
83
+            if (s2 < 0) {
84
+                break;
85
+            }
86
+        }
87
+    }
88
+
89
+    return size+s2;
90
+}
91
+
92
+int main (int argc, const char** argv)
93
+{
94
+    FILE* flv;
95
+    RTMP* rtmp;
96
+    RTMPPacket rtmpPacket;
97
+
98
+    flvtag_t tag;
99
+    int32_t timestamp = 0;
100
+    int has_audio, has_video;
101
+    char* url = 0;
102
+
103
+    if (2 >= argc) {
104
+        fprintf (stderr,"Usage %s [input] [url]\n",argv[0]);
105
+    }
106
+
107
+    url = (char*) argv[2];
108
+    flv = flv_open_read (argv[1]);
109
+
110
+    if (! flv) {
111
+        fprintf (stderr,"Could not open %s\n",argv[1]);
112
+        return EXIT_FAILURE;
113
+    }
114
+
115
+    if (! flv_read_header (flv, &has_audio, &has_video)) {
116
+        fprintf (stderr,"Not an flv file %s\n",argv[1]);
117
+        return EXIT_FAILURE;
118
+    }
119
+
120
+    flvtag_init (&tag);
121
+    rtmp = RTMP_Alloc();
122
+    RTMP_Init (rtmp);
123
+    fprintf (stderr,"Connecting to %s\n", url);
124
+    RTMP_SetupURL (rtmp, url);
125
+    RTMP_EnableWrite (rtmp);
126
+
127
+    RTMP_Connect (rtmp, NULL);
128
+    RTMP_ConnectStream (rtmp, 0);
129
+    memset (&rtmpPacket, 0, sizeof (RTMPPacket));
130
+
131
+    if (! RTMP_IsConnected (rtmp)) {
132
+        fprintf (stderr,"RTMP_IsConnected() Error\n");
133
+        return EXIT_FAILURE;
134
+    }
135
+
136
+    while (flv_read_tag (flv,&tag)) {
137
+        if (! RTMP_IsConnected (rtmp) || RTMP_IsTimedout (rtmp)) {
138
+            fprintf (stderr,"RTMP_IsConnected() Error\n");
139
+            return EXIT_FAILURE;
140
+        }
141
+
142
+        if (flvtag_timestamp (&tag) > timestamp) {
143
+            usleep (1000 * (flvtag_timestamp (&tag) - timestamp));
144
+            timestamp = flvtag_timestamp (&tag);
145
+        }
146
+
147
+        MyRTMP_Write (rtmp, (const char*) flvtag_raw_data (&tag),flvtag_raw_size (&tag));
148
+
149
+        // Handle RTMP ping and such
150
+        fd_set sockset; struct timeval timeout = {0,0};
151
+        FD_ZERO (&sockset); FD_SET (RTMP_Socket (rtmp), &sockset);
152
+        register int result = select (RTMP_Socket (rtmp) + 1, &sockset, NULL, NULL, &timeout);
153
+
154
+        if (result == 1 && FD_ISSET (RTMP_Socket (rtmp), &sockset)) {
155
+            RTMP_ReadPacket (rtmp, &rtmpPacket);
156
+
157
+            if (! RTMPPacket_IsReady (&rtmpPacket)) {
158
+                fprintf (stderr,"Received RTMP packet\n");
159
+                RTMP_ClientPacket (rtmp,&rtmpPacket);
160
+                RTMPPacket_Free (&rtmpPacket);
161
+            }
162
+        }
163
+    }
164
+
165
+    return EXIT_SUCCESS;
166
+}
167
obs-studio-0.17.0.tar.xz/deps/libcaption/examples/scc2srt.c Added
98
 
1
@@ -0,0 +1,96 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#include <stdio.h>
26
+#include <stdlib.h>
27
+#include <string.h>
28
+#include "srt.h"
29
+#include "scc.h"
30
+
31
+#define MAX_SCC_SIZE (10*1024*1024)
32
+#define MAX_READ_SIZE 4096
33
+#define MAX_CC 128
34
+
35
+size_t read_file (FILE* file, utf8_char_t* data, size_t size)
36
+{
37
+    size_t read, totl = 0;
38
+
39
+    while (0 < (read = fread (data,1,MAX_READ_SIZE<size?MAX_READ_SIZE:size,file))) {
40
+        totl += read; data += read; size -= read;
41
+    }
42
+
43
+    return totl;
44
+}
45
+
46
+srt_t* scc2srt (const char* data)
47
+{
48
+    double pts;
49
+    size_t line_size = 0;
50
+    int cc_idx, count, i;
51
+    srt_t* srt = 0, *head = 0;
52
+    caption_frame_t frame;
53
+    uint16_t cc_data[MAX_CC];
54
+
55
+    while (0 < (line_size = utf8_line_length (data))) {
56
+        caption_frame_init (&frame);
57
+        int cc_count = scc_to_608 (data, &pts, (uint16_t*) &cc_data, MAX_CC);
58
+        data += line_size;
59
+        data += utf8_line_length (data); // skip empty line
60
+
61
+        // fprintf (stderr,"%f, %d| %.*s\n", pts, cc_count, (int) line_size,data);
62
+
63
+        for (cc_idx = 0 ; cc_idx < cc_count ; ++cc_idx) {
64
+            // eia608_dump (cc_data[cc_idx]);
65
+            caption_frame_decode (&frame,cc_data[cc_idx],pts);
66
+        }
67
+
68
+        // utf8_char_t buff[CAPTION_FRAME_DUMP_BUF_SIZE];
69
+        // size_t size = caption_frame_dump (&frame, buff);
70
+        // fprintf (stderr,"%s\n", buff);
71
+        srt = srt_from_caption_frame (&frame,srt,&head);
72
+    }
73
+
74
+    return head;
75
+}
76
+
77
+int main (int argc, char** argv)
78
+{
79
+    char frame_buf[CAPTION_FRAME_DUMP_BUF_SIZE];
80
+
81
+    if (argc < 2) {
82
+        return 0;
83
+    }
84
+
85
+    FILE* file = fopen (argv[1],"r");
86
+
87
+    if (! file) {
88
+        return 0;
89
+    }
90
+
91
+    utf8_char_t* data = malloc (MAX_SCC_SIZE);
92
+    read_file (file,data,MAX_SCC_SIZE);
93
+    srt_t* srt = scc2srt (data);
94
+    srt_dump (srt);
95
+    srt_free (srt);
96
+    free (data);
97
+}
98
obs-studio-0.17.0.tar.xz/deps/libcaption/examples/srt2vtt.c Added
66
 
1
@@ -0,0 +1,64 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#include <stdio.h>
26
+#include <stdlib.h>
27
+#include <string.h>
28
+#include "srt.h"
29
+
30
+#define MAX_SRT_SIZE (10*1024*1024)
31
+#define MAX_READ_SIZE 4096
32
+
33
+size_t read_file (FILE* file, utf8_char_t* data, size_t size)
34
+{
35
+    size_t read, totl = 0;
36
+
37
+    while (0 < (read = fread (data,1,MAX_READ_SIZE<size?MAX_READ_SIZE:size,file))) {
38
+        totl += read; data += read; size -= read;
39
+    }
40
+
41
+    return totl;
42
+}
43
+
44
+int main (int argc, char** argv)
45
+{
46
+    srt_t* srt;
47
+    caption_frame_t frame;
48
+    char frame_buf[CAPTION_FRAME_DUMP_BUF_SIZE];
49
+
50
+    if (argc < 2) {
51
+        return 0;
52
+    }
53
+
54
+    FILE* file = fopen (argv[1],"r");
55
+
56
+    if (! file) {
57
+        return 0;
58
+    }
59
+
60
+    utf8_char_t* data = malloc (MAX_SRT_SIZE);
61
+    size_t size = read_file (file,data,MAX_SRT_SIZE);
62
+    srt_t* head = srt_parse (data,size);
63
+    vtt_dump (head);
64
+    srt_free (head);
65
+}
66
obs-studio-0.17.0.tar.xz/deps/libcaption/examples/srtdump.c Added
73
 
1
@@ -0,0 +1,71 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#include <stdio.h>
26
+#include <stdlib.h>
27
+#include <string.h>
28
+#include "srt.h"
29
+#include "avc.h"
30
+// #include "sei.h"
31
+
32
+#define MAX_SRT_SIZE (10*1024*1024)
33
+#define MAX_READ_SIZE 4096
34
+
35
+size_t read_file (FILE* file, utf8_char_t* data, size_t size)
36
+{
37
+    size_t read, totl = 0;
38
+
39
+    while (0 < (read = fread (data,1,MAX_READ_SIZE<size?MAX_READ_SIZE:size,file))) {
40
+        totl += read; data += read; size -= read;
41
+    }
42
+
43
+    return totl;
44
+}
45
+
46
+int main (int argc, char** argv)
47
+{
48
+    srt_t* srt;
49
+    caption_frame_t frame;
50
+
51
+    if (argc < 2) {
52
+        return 0;
53
+    }
54
+
55
+    FILE* file = fopen (argv[1],"r");
56
+
57
+    if (! file) {
58
+        return 0;
59
+    }
60
+
61
+    utf8_char_t* data = (utf8_char_t*) malloc (MAX_SRT_SIZE);
62
+    size_t size = read_file (file,data,MAX_SRT_SIZE);
63
+    srt_t* head = srt_parse (data,size);
64
+
65
+    for (srt = head ; srt ; srt = srt->next) {
66
+        caption_frame_init (&frame);
67
+        srt_to_caption_frame (srt,&frame);
68
+        caption_frame_dump (&frame);
69
+    }
70
+
71
+    srt_free (head);
72
+}
73
obs-studio-0.17.0.tar.xz/deps/libcaption/examples/ts.c Added
119
 
1
@@ -0,0 +1,117 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#include "ts.h"
26
+#include <string.h>
27
+
28
+void ts_init (ts_t* ts)
29
+{
30
+    memset (ts,0,sizeof (ts_t));
31
+}
32
+
33
+static int64_t ts_parse_pts (const uint8_t* data)
34
+{
35
+    // 0000 1110  1111 1111  1111 1110  1111 1111  1111 1110
36
+    uint64_t pts = 0;
37
+    pts |= (uint64_t) (data[0] & 0x0E) << 29;
38
+    pts |= (uint64_t) (data[1] & 0xFF) << 22;
39
+    pts |= (uint64_t) (data[2] & 0xFE) << 14;
40
+    pts |= (uint64_t) (data[3] & 0xFF) <<  7;
41
+    pts |= (uint64_t) (data[4] & 0xFE) >>  1;
42
+    return pts;
43
+}
44
+
45
+int ts_parse_packet (ts_t* ts, const uint8_t* data)
46
+{
47
+    size_t i = 0;
48
+    int pusi = !! (data[i + 1] & 0x40);  // Payload Unit Start Indicator
49
+    int16_t pid = ( (data[i + 1] & 0x1F) << 8) | data[i + 2];    // PID
50
+    int adaption_present = !! (data[i + 3] & 0x20);  // Adaptation field exist
51
+    int payload_present = !! (data[i + 3] & 0x10);  // Contains payload
52
+    i += 4;
53
+
54
+    ts->data = 0;
55
+    ts->size = 0;
56
+
57
+    if (adaption_present) {
58
+        uint8_t adaption_length = data[i + 0]; // adaption field length
59
+        i += 1 + adaption_length;
60
+    }
61
+
62
+    if (pid == 0) {
63
+        if (payload_present) {
64
+            // Skip the payload.
65
+            i += data[i] + 1;
66
+        }
67
+
68
+        ts->pmtpid = ( (data[i + 10] & 0x1F) << 8) | data[i + 11];
69
+    } else if (pid == ts->pmtpid) {
70
+        // PMT
71
+        if (payload_present) {
72
+            // Skip the payload.
73
+            i += data[i] + 1;
74
+        }
75
+
76
+        uint16_t section_length = ( (data[i + 1] & 0x0F) << 8) | data[i + 2];
77
+        int current = data[i + 5] & 0x01;
78
+        int16_t program_info_length = ( (data[i + 10] & 0x0F) << 8) | data[i + 11];
79
+        int16_t descriptor_loop_length = section_length - (9 + program_info_length + 4);   // 4 for the crc
80
+
81
+        i += 12 + program_info_length;
82
+
83
+        if (current) {
84
+            while (descriptor_loop_length >= 5) {
85
+                uint8_t stream_type    = data[i];
86
+                int16_t elementary_pid = ( (data[i + 1] & 0x1F) << 8) | data[i + 2];
87
+                int16_t esinfo_length  = ( (data[i + 3] & 0x0F) << 8) | data[i + 4];
88
+
89
+                if (0x1B == stream_type) {
90
+                    ts->avcpid = elementary_pid;
91
+                }
92
+
93
+                i += 5 + esinfo_length;
94
+                descriptor_loop_length -= 5 + esinfo_length;
95
+            }
96
+        }
97
+    } else if (payload_present && pid == ts->avcpid) {
98
+        if (pusi) {
99
+            // int data_alignment = !! (data[i + 6] & 0x04);
100
+            int has_pts = !! (data[i + 7] & 0x80);
101
+            int has_dts = !! (data[i + 7] & 0x40);
102
+            uint8_t header_length = data[i + 8];
103
+
104
+            if (has_pts) {
105
+                ts->pts = ts_parse_pts (&data[i + 9]);
106
+                ts->dts = has_dts ? ts_parse_pts (&data[i + 14]) : ts->pts;
107
+            }
108
+
109
+            i += 9 + header_length;
110
+        }
111
+
112
+        ts->data = &data[i];
113
+        ts->size = TS_PACKET_SIZE-i;
114
+        return LIBCAPTION_READY;
115
+    }
116
+
117
+    return LIBCAPTION_OK;
118
+}
119
obs-studio-0.17.0.tar.xz/deps/libcaption/examples/ts.h Added
51
 
1
@@ -0,0 +1,49 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#ifndef LIBCAPTION_TS_H
26
+#define LIBCAPTION_TS_H
27
+#include "caption.h"
28
+typedef struct {
29
+    int16_t pmtpid;
30
+    int16_t avcpid;
31
+    int64_t pts;
32
+    int64_t dts;
33
+    size_t  size;
34
+    const uint8_t* data;
35
+} ts_t;
36
+
37
+/*! \brief
38
+    \param
39
+
40
+    Expects 188 byte TS packet
41
+*/
42
+#define TS_PACKET_SIZE 188
43
+void ts_init (ts_t* ts);
44
+int ts_parse_packet (ts_t* ts, const uint8_t* data);
45
+// return timestamp in seconds
46
+static inline double ts_dts_seconds (ts_t* ts) { return ts->dts / 90000.0; }
47
+static inline double ts_pts_seconds (ts_t* ts) { return ts->pts / 90000.0; }
48
+static inline double ts_cts_seconds (ts_t* ts) { return (ts->dts - ts->pts) / 90000.0; }
49
+
50
+#endif
51
obs-studio-0.17.0.tar.xz/deps/libcaption/examples/ts2srt.c Added
103
 
1
@@ -0,0 +1,101 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#include "ts.h"
26
+#include "srt.h"
27
+#include "avc.h"
28
+#include <stdio.h>
29
+
30
+int main (int argc, char** argv)
31
+{
32
+    const char* path = argv[1];
33
+
34
+    ts_t ts;
35
+    sei_t sei;
36
+    avcnalu_t nalu;
37
+    srt_t* srt = 0, *head = 0;
38
+    caption_frame_t frame;
39
+    uint8_t pkt[TS_PACKET_SIZE];
40
+    ts_init (&ts);
41
+    avcnalu_init (&nalu);
42
+    caption_frame_init (&frame);
43
+
44
+    FILE* file = fopen (path,"rb+");
45
+
46
+    while (TS_PACKET_SIZE == fread (&pkt[0],1,TS_PACKET_SIZE, file)) {
47
+        switch (ts_parse_packet (&ts,&pkt[0])) {
48
+        case LIBCAPTION_OK:
49
+            // fprintf (stderr,"read ts packet\n");
50
+            break;
51
+
52
+        case LIBCAPTION_READY: {
53
+            // fprintf (stderr,"read ts packet DATA\n");
54
+            while (ts.size) {
55
+                // fprintf (stderr,"ts.size %d (%02X%02X%02X%02X)\n",ts.size, ts.data[0], ts.data[1], ts.data[2], ts.data[3]);
56
+
57
+                switch (avcnalu_parse_annexb (&nalu, &ts.data, &ts.size)) {
58
+                case LIBCAPTION_OK:
59
+                    break;
60
+
61
+                case LIBCAPTION_ERROR:
62
+                    // fprintf (stderr,"LIBCAPTION_ERROR == avcnalu_parse_annexb()\n");
63
+                    avcnalu_init (&nalu);
64
+                    break;
65
+
66
+                case LIBCAPTION_READY: {
67
+
68
+                    if (6 == avcnalu_type (&nalu)) {
69
+                        // fprintf (stderr,"NALU %d (%d)\n", avcnalu_type (&nalu), avcnalu_size (&nalu));
70
+                        sei_init (&sei);
71
+                        sei_parse_avcnalu (&sei, &nalu, ts_dts_seconds (&ts), ts_cts_seconds (&ts));
72
+
73
+                        // sei_dump (&sei);
74
+
75
+                        if (LIBCAPTION_READY == sei_to_caption_frame (&sei,&frame)) {
76
+                            // caption_frame_dump (&frame);
77
+                            srt = srt_from_caption_frame (&frame,srt,&head);
78
+
79
+                            // srt_dump (srt);
80
+                        }
81
+
82
+                        sei_free (&sei);
83
+                    }
84
+
85
+                    avcnalu_init (&nalu);
86
+                } break;
87
+                }
88
+            }
89
+        } break;
90
+
91
+        case LIBCAPTION_ERROR:
92
+            // fprintf (stderr,"read ts packet ERROR\n");
93
+            break;
94
+        }
95
+
96
+    }
97
+
98
+    srt_dump (head);
99
+    srt_free (head);
100
+
101
+    return 1;
102
+}
103
obs-studio-0.17.0.tar.xz/deps/libcaption/examples/wonderland.h Added
2796
 
1
@@ -0,0 +1,2794 @@
2
+const char* wonderland[] = {
3
+    "Project Gutenberg’s Alice’s Adventures in Wonderland, by Lewis Carroll",
4
+    "This eBook is for the use of anyone anywhere at no cost and with",
5
+    "almost no restrictions whatsoever.  You may copy it, give it away or",
6
+    "re-use it under the terms of the Project Gutenberg License included",
7
+    "with this eBook or online at www.gutenberg.org",
8
+    "Title: Alice’s Adventures in Wonderland",
9
+    "Author: Lewis Carroll",
10
+    "Posting Date: June 25, 2008 [EBook #11]",
11
+    "Release Date: March, 1994",
12
+    "Last Updated: October 6, 2016",
13
+    "Language: English",
14
+    "Character set encoding: UTF-8",
15
+    "*** START OF THIS PROJECT GUTENBERG EBOOK ALICE’S ADVENTURES IN WONDERLAND ***",
16
+    "ALICE’S ADVENTURES IN WONDERLAND",
17
+    "Lewis Carroll",
18
+    "THE MILLENNIUM FULCRUM EDITION 3.0",
19
+    "CHAPTER I. Down the Rabbit-Hole",
20
+    "Alice was beginning to get very tired of sitting by her sister on the",
21
+    "bank, and of having nothing to do: once or twice she had peeped into the",
22
+    "book her sister was reading, but it had no pictures or conversations in",
23
+    "it, ‘and what is the use of a book,’ thought Alice ‘without pictures or",
24
+    "conversations?’",
25
+    "So she was considering in her own mind (as well as she could, for the",
26
+    "hot day made her feel very sleepy and stupid), whether the pleasure",
27
+    "of making a daisy-chain would be worth the trouble of getting up and",
28
+    "picking the daisies, when suddenly a White Rabbit with pink eyes ran",
29
+    "close by her.",
30
+    "There was nothing so VERY remarkable in that; nor did Alice think it so",
31
+    "VERY much out of the way to hear the Rabbit say to itself, ‘Oh dear!",
32
+    "Oh dear! I shall be late!’ (when she thought it over afterwards, it",
33
+    "occurred to her that she ought to have wondered at this, but at the time",
34
+    "it all seemed quite natural); but when the Rabbit actually TOOK A WATCH",
35
+    "OUT OF ITS WAISTCOAT-POCKET, and looked at it, and then hurried on,",
36
+    "Alice started to her feet, for it flashed across her mind that she had",
37
+    "never before seen a rabbit with either a waistcoat-pocket, or a watch",
38
+    "to take out of it, and burning with curiosity, she ran across the field",
39
+    "after it, and fortunately was just in time to see it pop down a large",
40
+    "rabbit-hole under the hedge.",
41
+    "In another moment down went Alice after it, never once considering how",
42
+    "in the world she was to get out again.",
43
+    "The rabbit-hole went straight on like a tunnel for some way, and then",
44
+    "dipped suddenly down, so suddenly that Alice had not a moment to think",
45
+    "about stopping herself before she found herself falling down a very deep",
46
+    "well.",
47
+    "Either the well was very deep, or she fell very slowly, for she had",
48
+    "plenty of time as she went down to look about her and to wonder what was",
49
+    "going to happen next. First, she tried to look down and make out what",
50
+    "she was coming to, but it was too dark to see anything; then she",
51
+    "looked at the sides of the well, and noticed that they were filled with",
52
+    "cupboards and book-shelves; here and there she saw maps and pictures",
53
+    "hung upon pegs. She took down a jar from one of the shelves as",
54
+    "she passed; it was labelled ‘ORANGE MARMALADE’, but to her great",
55
+    "disappointment it was empty: she did not like to drop the jar for fear",
56
+    "of killing somebody, so managed to put it into one of the cupboards as",
57
+    "she fell past it.",
58
+    "‘Well!’ thought Alice to herself, ‘after such a fall as this, I shall",
59
+    "think nothing of tumbling down stairs! How brave they’ll all think me at",
60
+    "home! Why, I wouldn’t say anything about it, even if I fell off the top",
61
+    "of the house!’ (Which was very likely true.)",
62
+    "Down, down, down. Would the fall NEVER come to an end! ‘I wonder how",
63
+    "many miles I’ve fallen by this time?’ she said aloud. ‘I must be getting",
64
+    "somewhere near the centre of the earth. Let me see: that would be four",
65
+    "thousand miles down, I think--’ (for, you see, Alice had learnt several",
66
+    "things of this sort in her lessons in the schoolroom, and though this",
67
+    "was not a VERY good opportunity for showing off her knowledge, as there",
68
+    "was no one to listen to her, still it was good practice to say it over)",
69
+    "‘--yes, that’s about the right distance--but then I wonder what Latitude",
70
+    "or Longitude I’ve got to?’ (Alice had no idea what Latitude was, or",
71
+    "Longitude either, but thought they were nice grand words to say.)",
72
+    "Presently she began again. ‘I wonder if I shall fall right THROUGH the",
73
+    "earth! How funny it’ll seem to come out among the people that walk with",
74
+    "their heads downward! The Antipathies, I think--’ (she was rather glad",
75
+    "there WAS no one listening, this time, as it didn’t sound at all the",
76
+    "right word) ‘--but I shall have to ask them what the name of the country",
77
+    "is, you know. Please, Ma’am, is this New Zealand or Australia?’ (and",
78
+    "she tried to curtsey as she spoke--fancy CURTSEYING as you’re falling",
79
+    "through the air! Do you think you could manage it?) ‘And what an",
80
+    "ignorant little girl she’ll think me for asking! No, it’ll never do to",
81
+    "ask: perhaps I shall see it written up somewhere.’",
82
+    "Down, down, down. There was nothing else to do, so Alice soon began",
83
+    "talking again. ‘Dinah’ll miss me very much to-night, I should think!’",
84
+    "(Dinah was the cat.) ‘I hope they’ll remember her saucer of milk at",
85
+    "tea-time. Dinah my dear! I wish you were down here with me! There are no",
86
+    "mice in the air, I’m afraid, but you might catch a bat, and that’s very",
87
+    "like a mouse, you know. But do cats eat bats, I wonder?’ And here Alice",
88
+    "began to get rather sleepy, and went on saying to herself, in a dreamy",
89
+    "sort of way, ‘Do cats eat bats? Do cats eat bats?’ and sometimes, ‘Do",
90
+    "bats eat cats?’ for, you see, as she couldn’t answer either question,",
91
+    "it didn’t much matter which way she put it. She felt that she was dozing",
92
+    "off, and had just begun to dream that she was walking hand in hand with",
93
+    "Dinah, and saying to her very earnestly, ‘Now, Dinah, tell me the truth:",
94
+    "did you ever eat a bat?’ when suddenly, thump! thump! down she came upon",
95
+    "a heap of sticks and dry leaves, and the fall was over.",
96
+    "Alice was not a bit hurt, and she jumped up on to her feet in a moment:",
97
+    "she looked up, but it was all dark overhead; before her was another",
98
+    "long passage, and the White Rabbit was still in sight, hurrying down it.",
99
+    "There was not a moment to be lost: away went Alice like the wind, and",
100
+    "was just in time to hear it say, as it turned a corner, ‘Oh my ears",
101
+    "and whiskers, how late it’s getting!’ She was close behind it when she",
102
+    "turned the corner, but the Rabbit was no longer to be seen: she found",
103
+    "herself in a long, low hall, which was lit up by a row of lamps hanging",
104
+    "from the roof.",
105
+    "There were doors all round the hall, but they were all locked; and when",
106
+    "Alice had been all the way down one side and up the other, trying every",
107
+    "door, she walked sadly down the middle, wondering how she was ever to",
108
+    "get out again.",
109
+    "Suddenly she came upon a little three-legged table, all made of solid",
110
+    "glass; there was nothing on it except a tiny golden key, and Alice’s",
111
+    "first thought was that it might belong to one of the doors of the hall;",
112
+    "but, alas! either the locks were too large, or the key was too small,",
113
+    "but at any rate it would not open any of them. However, on the second",
114
+    "time round, she came upon a low curtain she had not noticed before, and",
115
+    "behind it was a little door about fifteen inches high: she tried the",
116
+    "little golden key in the lock, and to her great delight it fitted!",
117
+    "Alice opened the door and found that it led into a small passage, not",
118
+    "much larger than a rat-hole: she knelt down and looked along the passage",
119
+    "into the loveliest garden you ever saw. How she longed to get out of",
120
+    "that dark hall, and wander about among those beds of bright flowers and",
121
+    "those cool fountains, but she could not even get her head through the",
122
+    "doorway; ‘and even if my head would go through,’ thought poor Alice, ‘it",
123
+    "would be of very little use without my shoulders. Oh, how I wish I could",
124
+    "shut up like a telescope! I think I could, if I only knew how to begin.’",
125
+    "For, you see, so many out-of-the-way things had happened lately,",
126
+    "that Alice had begun to think that very few things indeed were really",
127
+    "impossible.",
128
+    "There seemed to be no use in waiting by the little door, so she went",
129
+    "back to the table, half hoping she might find another key on it, or at",
130
+    "any rate a book of rules for shutting people up like telescopes: this",
131
+    "time she found a little bottle on it, [‘which certainly was not here",
132
+    "before,’ said Alice,) and round the neck of the bottle was a paper",
133
+    "label, with the words ‘DRINK ME’ beautifully printed on it in large",
134
+    "letters.",
135
+    "It was all very well to say ‘Drink me,’ but the wise little Alice was",
136
+    "not going to do THAT in a hurry. ‘No, I’ll look first,’ she said, ‘and",
137
+    "see whether it’s marked “poison” or not’; for she had read several nice",
138
+    "little histories about children who had got burnt, and eaten up by wild",
139
+    "beasts and other unpleasant things, all because they WOULD not remember",
140
+    "the simple rules their friends had taught them: such as, that a red-hot",
141
+    "poker will burn you if you hold it too long; and that if you cut your",
142
+    "finger VERY deeply with a knife, it usually bleeds; and she had never",
143
+    "forgotten that, if you drink much from a bottle marked ‘poison,’ it is",
144
+    "almost certain to disagree with you, sooner or later.",
145
+    "However, this bottle was NOT marked ‘poison,’ so Alice ventured to taste",
146
+    "it, and finding it very nice, (it had, in fact, a sort of mixed flavour",
147
+    "of cherry-tart, custard, pine-apple, roast turkey, toffee, and hot",
148
+    "buttered toast,) she very soon finished it off.",
149
+    "  *    *    *    *    *    *    *",
150
+    "    *    *    *    *    *    *",
151
+    "  *    *    *    *    *    *    *",
152
+    "‘What a curious feeling!’ said Alice; ‘I must be shutting up like a",
153
+    "telescope.’",
154
+    "And so it was indeed: she was now only ten inches high, and her face",
155
+    "brightened up at the thought that she was now the right size for going",
156
+    "through the little door into that lovely garden. First, however, she",
157
+    "waited for a few minutes to see if she was going to shrink any further:",
158
+    "she felt a little nervous about this; ‘for it might end, you know,’ said",
159
+    "Alice to herself, ‘in my going out altogether, like a candle. I wonder",
160
+    "what I should be like then?’ And she tried to fancy what the flame of a",
161
+    "candle is like after the candle is blown out, for she could not remember",
162
+    "ever having seen such a thing.",
163
+    "After a while, finding that nothing more happened, she decided on going",
164
+    "into the garden at once; but, alas for poor Alice! when she got to the",
165
+    "door, she found she had forgotten the little golden key, and when she",
166
+    "went back to the table for it, she found she could not possibly reach",
167
+    "it: she could see it quite plainly through the glass, and she tried her",
168
+    "best to climb up one of the legs of the table, but it was too slippery;",
169
+    "and when she had tired herself out with trying, the poor little thing",
170
+    "sat down and cried.",
171
+    "‘Come, there’s no use in crying like that!’ said Alice to herself,",
172
+    "rather sharply; ‘I advise you to leave off this minute!’ She generally",
173
+    "gave herself very good advice, (though she very seldom followed it),",
174
+    "and sometimes she scolded herself so severely as to bring tears into",
175
+    "her eyes; and once she remembered trying to box her own ears for having",
176
+    "cheated herself in a game of croquet she was playing against herself,",
177
+    "for this curious child was very fond of pretending to be two people.",
178
+    "‘But it’s no use now,’ thought poor Alice, ‘to pretend to be two people!",
179
+    "Why, there’s hardly enough of me left to make ONE respectable person!’",
180
+    "Soon her eye fell on a little glass box that was lying under the table:",
181
+    "she opened it, and found in it a very small cake, on which the words",
182
+    "‘EAT ME’ were beautifully marked in currants. ‘Well, I’ll eat it,’ said",
183
+    "Alice, ‘and if it makes me grow larger, I can reach the key; and if it",
184
+    "makes me grow smaller, I can creep under the door; so either way I’ll",
185
+    "get into the garden, and I don’t care which happens!’",
186
+    "She ate a little bit, and said anxiously to herself, ‘Which way? Which",
187
+    "way?’, holding her hand on the top of her head to feel which way it was",
188
+    "growing, and she was quite surprised to find that she remained the same",
189
+    "size: to be sure, this generally happens when one eats cake, but Alice",
190
+    "had got so much into the way of expecting nothing but out-of-the-way",
191
+    "things to happen, that it seemed quite dull and stupid for life to go on",
192
+    "in the common way.",
193
+    "So she set to work, and very soon finished off the cake.",
194
+    "  *    *    *    *    *    *    *",
195
+    "    *    *    *    *    *    *",
196
+    "  *    *    *    *    *    *    *",
197
+    "CHAPTER II. The Pool of Tears",
198
+    "‘Curiouser and curiouser!’ cried Alice (she was so much surprised, that",
199
+    "for the moment she quite forgot how to speak good English); ‘now I’m",
200
+    "opening out like the largest telescope that ever was! Good-bye, feet!’",
201
+    "(for when she looked down at her feet, they seemed to be almost out of",
202
+    "sight, they were getting so far off). ‘Oh, my poor little feet, I wonder",
203
+    "who will put on your shoes and stockings for you now, dears? I’m sure",
204
+    "_I_ shan’t be able! I shall be a great deal too far off to trouble",
205
+    "myself about you: you must manage the best way you can;--but I must be",
206
+    "kind to them,’ thought Alice, ‘or perhaps they won’t walk the way I want",
207
+    "to go! Let me see: I’ll give them a new pair of boots every Christmas.’",
208
+    "And she went on planning to herself how she would manage it. ‘They must",
209
+    "go by the carrier,’ she thought; ‘and how funny it’ll seem, sending",
210
+    "presents to one’s own feet! And how odd the directions will look!",
211
+    "     ALICE’S RIGHT FOOT, ESQ.",
212
+    "       HEARTHRUG,",
213
+    "         NEAR THE FENDER,",
214
+    "           (WITH ALICE’S LOVE).",
215
+    "Oh dear, what nonsense I’m talking!’",
216
+    "Just then her head struck against the roof of the hall: in fact she was",
217
+    "now more than nine feet high, and she at once took up the little golden",
218
+    "key and hurried off to the garden door.",
219
+    "Poor Alice! It was as much as she could do, lying down on one side, to",
220
+    "look through into the garden with one eye; but to get through was more",
221
+    "hopeless than ever: she sat down and began to cry again.",
222
+    "‘You ought to be ashamed of yourself,’ said Alice, ‘a great girl like",
223
+    "you,’ (she might well say this), ‘to go on crying in this way! Stop this",
224
+    "moment, I tell you!’ But she went on all the same, shedding gallons of",
225
+    "tears, until there was a large pool all round her, about four inches",
226
+    "deep and reaching half down the hall.",
227
+    "After a time she heard a little pattering of feet in the distance, and",
228
+    "she hastily dried her eyes to see what was coming. It was the White",
229
+    "Rabbit returning, splendidly dressed, with a pair of white kid gloves in",
230
+    "one hand and a large fan in the other: he came trotting along in a great",
231
+    "hurry, muttering to himself as he came, ‘Oh! the Duchess, the Duchess!",
232
+    "Oh! won’t she be savage if I’ve kept her waiting!’ Alice felt so",
233
+    "desperate that she was ready to ask help of any one; so, when the Rabbit",
234
+    "came near her, she began, in a low, timid voice, ‘If you please, sir--’",
235
+    "The Rabbit started violently, dropped the white kid gloves and the fan,",
236
+    "and skurried away into the darkness as hard as he could go.",
237
+    "Alice took up the fan and gloves, and, as the hall was very hot, she",
238
+    "kept fanning herself all the time she went on talking: ‘Dear, dear! How",
239
+    "queer everything is to-day! And yesterday things went on just as usual.",
240
+    "I wonder if I’ve been changed in the night? Let me think: was I the",
241
+    "same when I got up this morning? I almost think I can remember feeling a",
242
+    "little different. But if I’m not the same, the next question is, Who",
243
+    "in the world am I? Ah, THAT’S the great puzzle!’ And she began thinking",
244
+    "over all the children she knew that were of the same age as herself, to",
245
+    "see if she could have been changed for any of them.",
246
+    "‘I’m sure I’m not Ada,’ she said, ‘for her hair goes in such long",
247
+    "ringlets, and mine doesn’t go in ringlets at all; and I’m sure I can’t",
248
+    "be Mabel, for I know all sorts of things, and she, oh! she knows such a",
249
+    "very little! Besides, SHE’S she, and I’m I, and--oh dear, how puzzling",
250
+    "it all is! I’ll try if I know all the things I used to know. Let me",
251
+    "see: four times five is twelve, and four times six is thirteen, and",
252
+    "four times seven is--oh dear! I shall never get to twenty at that rate!",
253
+    "However, the Multiplication Table doesn’t signify: let’s try Geography.",
254
+    "London is the capital of Paris, and Paris is the capital of Rome, and",
255
+    "Rome--no, THAT’S all wrong, I’m certain! I must have been changed for",
256
+    "Mabel! I’ll try and say “How doth the little--“’ and she crossed her",
257
+    "hands on her lap as if she were saying lessons, and began to repeat it,",
258
+    "but her voice sounded hoarse and strange, and the words did not come the",
259
+    "same as they used to do:--",
260
+    "     ‘How doth the little crocodile",
261
+    "      Improve his shining tail,",
262
+    "     And pour the waters of the Nile",
263
+    "      On every golden scale!",
264
+    "     ‘How cheerfully he seems to grin,",
265
+    "      How neatly spread his claws,",
266
+    "     And welcome little fishes in",
267
+    "      With gently smiling jaws!’",
268
+    "‘I’m sure those are not the right words,’ said poor Alice, and her eyes",
269
+    "filled with tears again as she went on, ‘I must be Mabel after all, and",
270
+    "I shall have to go and live in that poky little house, and have next to",
271
+    "no toys to play with, and oh! ever so many lessons to learn! No, I’ve",
272
+    "made up my mind about it; if I’m Mabel, I’ll stay down here! It’ll be no",
273
+    "use their putting their heads down and saying “Come up again, dear!” I",
274
+    "shall only look up and say “Who am I then? Tell me that first, and then,",
275
+    "if I like being that person, I’ll come up: if not, I’ll stay down here",
276
+    "till I’m somebody else”--but, oh dear!’ cried Alice, with a sudden burst",
277
+    "of tears, ‘I do wish they WOULD put their heads down! I am so VERY tired",
278
+    "of being all alone here!’",
279
+    "As she said this she looked down at her hands, and was surprised to see",
280
+    "that she had put on one of the Rabbit’s little white kid gloves while",
281
+    "she was talking. ‘How CAN I have done that?’ she thought. ‘I must",
282
+    "be growing small again.’ She got up and went to the table to measure",
283
+    "herself by it, and found that, as nearly as she could guess, she was now",
284
+    "about two feet high, and was going on shrinking rapidly: she soon found",
285
+    "out that the cause of this was the fan she was holding, and she dropped",
286
+    "it hastily, just in time to avoid shrinking away altogether.",
287
+    "‘That WAS a narrow escape!’ said Alice, a good deal frightened at the",
288
+    "sudden change, but very glad to find herself still in existence; ‘and",
289
+    "now for the garden!’ and she ran with all speed back to the little door:",
290
+    "but, alas! the little door was shut again, and the little golden key was",
291
+    "lying on the glass table as before, ‘and things are worse than ever,’",
292
+    "thought the poor child, ‘for I never was so small as this before, never!",
293
+    "And I declare it’s too bad, that it is!’",
294
+    "As she said these words her foot slipped, and in another moment, splash!",
295
+    "she was up to her chin in salt water. Her first idea was that she",
296
+    "had somehow fallen into the sea, ‘and in that case I can go back by",
297
+    "railway,’ she said to herself. (Alice had been to the seaside once in",
298
+    "her life, and had come to the general conclusion, that wherever you go",
299
+    "to on the English coast you find a number of bathing machines in the",
300
+    "sea, some children digging in the sand with wooden spades, then a row",
301
+    "of lodging houses, and behind them a railway station.) However, she soon",
302
+    "made out that she was in the pool of tears which she had wept when she",
303
+    "was nine feet high.",
304
+    "‘I wish I hadn’t cried so much!’ said Alice, as she swam about, trying",
305
+    "to find her way out. ‘I shall be punished for it now, I suppose, by",
306
+    "being drowned in my own tears! That WILL be a queer thing, to be sure!",
307
+    "However, everything is queer to-day.’",
308
+    "Just then she heard something splashing about in the pool a little way",
309
+    "off, and she swam nearer to make out what it was: at first she thought",
310
+    "it must be a walrus or hippopotamus, but then she remembered how small",
311
+    "she was now, and she soon made out that it was only a mouse that had",
312
+    "slipped in like herself.",
313
+    "‘Would it be of any use, now,’ thought Alice, ‘to speak to this mouse?",
314
+    "Everything is so out-of-the-way down here, that I should think very",
315
+    "likely it can talk: at any rate, there’s no harm in trying.’ So she",
316
+    "began: ‘O Mouse, do you know the way out of this pool? I am very tired",
317
+    "of swimming about here, O Mouse!’ (Alice thought this must be the right",
318
+    "way of speaking to a mouse: she had never done such a thing before, but",
319
+    "she remembered having seen in her brother’s Latin Grammar, ‘A mouse--of",
320
+    "a mouse--to a mouse--a mouse--O mouse!’) The Mouse looked at her rather",
321
+    "inquisitively, and seemed to her to wink with one of its little eyes,",
322
+    "but it said nothing.",
323
+    "‘Perhaps it doesn’t understand English,’ thought Alice; ‘I daresay it’s",
324
+    "a French mouse, come over with William the Conqueror.’ (For, with all",
325
+    "her knowledge of history, Alice had no very clear notion how long ago",
326
+    "anything had happened.) So she began again: ‘Ou est ma chatte?’ which",
327
+    "was the first sentence in her French lesson-book. The Mouse gave a",
328
+    "sudden leap out of the water, and seemed to quiver all over with fright.",
329
+    "‘Oh, I beg your pardon!’ cried Alice hastily, afraid that she had hurt",
330
+    "the poor animal’s feelings. ‘I quite forgot you didn’t like cats.’",
331
+    "‘Not like cats!’ cried the Mouse, in a shrill, passionate voice. ‘Would",
332
+    "YOU like cats if you were me?’",
333
+    "‘Well, perhaps not,’ said Alice in a soothing tone: ‘don’t be angry",
334
+    "about it. And yet I wish I could show you our cat Dinah: I think you’d",
335
+    "take a fancy to cats if you could only see her. She is such a dear quiet",
336
+    "thing,’ Alice went on, half to herself, as she swam lazily about in the",
337
+    "pool, ‘and she sits purring so nicely by the fire, licking her paws and",
338
+    "washing her face--and she is such a nice soft thing to nurse--and she’s",
339
+    "such a capital one for catching mice--oh, I beg your pardon!’ cried",
340
+    "Alice again, for this time the Mouse was bristling all over, and she",
341
+    "felt certain it must be really offended. ‘We won’t talk about her any",
342
+    "more if you’d rather not.’",
343
+    "‘We indeed!’ cried the Mouse, who was trembling down to the end of his",
344
+    "tail. ‘As if I would talk on such a subject! Our family always HATED",
345
+    "cats: nasty, low, vulgar things! Don’t let me hear the name again!’",
346
+    "‘I won’t indeed!’ said Alice, in a great hurry to change the subject of",
347
+    "conversation. ‘Are you--are you fond--of--of dogs?’ The Mouse did not",
348
+    "answer, so Alice went on eagerly: ‘There is such a nice little dog near",
349
+    "our house I should like to show you! A little bright-eyed terrier, you",
350
+    "know, with oh, such long curly brown hair! And it’ll fetch things when",
351
+    "you throw them, and it’ll sit up and beg for its dinner, and all sorts",
352
+    "of things--I can’t remember half of them--and it belongs to a farmer,",
353
+    "you know, and he says it’s so useful, it’s worth a hundred pounds! He",
354
+    "says it kills all the rats and--oh dear!’ cried Alice in a sorrowful",
355
+    "tone, ‘I’m afraid I’ve offended it again!’ For the Mouse was swimming",
356
+    "away from her as hard as it could go, and making quite a commotion in",
357
+    "the pool as it went.",
358
+    "So she called softly after it, ‘Mouse dear! Do come back again, and we",
359
+    "won’t talk about cats or dogs either, if you don’t like them!’ When the",
360
+    "Mouse heard this, it turned round and swam slowly back to her: its",
361
+    "face was quite pale (with passion, Alice thought), and it said in a low",
362
+    "trembling voice, ‘Let us get to the shore, and then I’ll tell you my",
363
+    "history, and you’ll understand why it is I hate cats and dogs.’",
364
+    "It was high time to go, for the pool was getting quite crowded with the",
365
+    "birds and animals that had fallen into it: there were a Duck and a Dodo,",
366
+    "a Lory and an Eaglet, and several other curious creatures. Alice led the",
367
+    "way, and the whole party swam to the shore.",
368
+    "CHAPTER III. A Caucus-Race and a Long Tale",
369
+    "They were indeed a queer-looking party that assembled on the bank--the",
370
+    "birds with draggled feathers, the animals with their fur clinging close",
371
+    "to them, and all dripping wet, cross, and uncomfortable.",
372
+    "The first question of course was, how to get dry again: they had a",
373
+    "consultation about this, and after a few minutes it seemed quite natural",
374
+    "to Alice to find herself talking familiarly with them, as if she had",
375
+    "known them all her life. Indeed, she had quite a long argument with the",
376
+    "Lory, who at last turned sulky, and would only say, ‘I am older than",
377
+    "you, and must know better’; and this Alice would not allow without",
378
+    "knowing how old it was, and, as the Lory positively refused to tell its",
379
+    "age, there was no more to be said.",
380
+    "At last the Mouse, who seemed to be a person of authority among them,",
381
+    "called out, ‘Sit down, all of you, and listen to me! I’LL soon make you",
382
+    "dry enough!’ They all sat down at once, in a large ring, with the Mouse",
383
+    "in the middle. Alice kept her eyes anxiously fixed on it, for she felt",
384
+    "sure she would catch a bad cold if she did not get dry very soon.",
385
+    "‘Ahem!’ said the Mouse with an important air, ‘are you all ready? This",
386
+    "is the driest thing I know. Silence all round, if you please! “William",
387
+    "the Conqueror, whose cause was favoured by the pope, was soon submitted",
388
+    "to by the English, who wanted leaders, and had been of late much",
389
+    "accustomed to usurpation and conquest. Edwin and Morcar, the earls of",
390
+    "Mercia and Northumbria--“’",
391
+    "‘Ugh!’ said the Lory, with a shiver.",
392
+    "‘I beg your pardon!’ said the Mouse, frowning, but very politely: ‘Did",
393
+    "you speak?’",
394
+    "‘Not I!’ said the Lory hastily.",
395
+    "‘I thought you did,’ said the Mouse. ‘--I proceed. “Edwin and Morcar,",
396
+    "the earls of Mercia and Northumbria, declared for him: and even Stigand,",
397
+    "the patriotic archbishop of Canterbury, found it advisable--“’",
398
+    "‘Found WHAT?’ said the Duck.",
399
+    "‘Found IT,’ the Mouse replied rather crossly: ‘of course you know what",
400
+    "“it” means.’",
401
+    "‘I know what “it” means well enough, when I find a thing,’ said the",
402
+    "Duck: ‘it’s generally a frog or a worm. The question is, what did the",
403
+    "archbishop find?’",
404
+    "The Mouse did not notice this question, but hurriedly went on, ‘“--found",
405
+    "it advisable to go with Edgar Atheling to meet William and offer him the",
406
+    "crown. William’s conduct at first was moderate. But the insolence of his",
407
+    "Normans--” How are you getting on now, my dear?’ it continued, turning",
408
+    "to Alice as it spoke.",
409
+    "‘As wet as ever,’ said Alice in a melancholy tone: ‘it doesn’t seem to",
410
+    "dry me at all.’",
411
+    "‘In that case,’ said the Dodo solemnly, rising to its feet, ‘I move",
412
+    "that the meeting adjourn, for the immediate adoption of more energetic",
413
+    "remedies--’",
414
+    "‘Speak English!’ said the Eaglet. ‘I don’t know the meaning of half",
415
+    "those long words, and, what’s more, I don’t believe you do either!’ And",
416
+    "the Eaglet bent down its head to hide a smile: some of the other birds",
417
+    "tittered audibly.",
418
+    "‘What I was going to say,’ said the Dodo in an offended tone, ‘was, that",
419
+    "the best thing to get us dry would be a Caucus-race.’",
420
+    "‘What IS a Caucus-race?’ said Alice; not that she wanted much to know,",
421
+    "but the Dodo had paused as if it thought that SOMEBODY ought to speak,",
422
+    "and no one else seemed inclined to say anything.",
423
+    "‘Why,’ said the Dodo, ‘the best way to explain it is to do it.’ (And, as",
424
+    "you might like to try the thing yourself, some winter day, I will tell",
425
+    "you how the Dodo managed it.)",
426
+    "First it marked out a race-course, in a sort of circle, [‘the exact",
427
+    "shape doesn’t matter,’ it said,) and then all the party were placed",
428
+    "along the course, here and there. There was no ‘One, two, three, and",
429
+    "away,’ but they began running when they liked, and left off when they",
430
+    "liked, so that it was not easy to know when the race was over. However,",
431
+    "when they had been running half an hour or so, and were quite dry again,",
432
+    "the Dodo suddenly called out ‘The race is over!’ and they all crowded",
433
+    "round it, panting, and asking, ‘But who has won?’",
434
+    "This question the Dodo could not answer without a great deal of thought,",
435
+    "and it sat for a long time with one finger pressed upon its forehead",
436
+    "(the position in which you usually see Shakespeare, in the pictures",
437
+    "of him), while the rest waited in silence. At last the Dodo said,",
438
+    "‘EVERYBODY has won, and all must have prizes.’",
439
+    "‘But who is to give the prizes?’ quite a chorus of voices asked.",
440
+    "‘Why, SHE, of course,’ said the Dodo, pointing to Alice with one finger;",
441
+    "and the whole party at once crowded round her, calling out in a confused",
442
+    "way, ‘Prizes! Prizes!’",
443
+    "Alice had no idea what to do, and in despair she put her hand in her",
444
+    "pocket, and pulled out a box of comfits, (luckily the salt water had",
445
+    "not got into it), and handed them round as prizes. There was exactly one",
446
+    "a-piece all round.",
447
+    "‘But she must have a prize herself, you know,’ said the Mouse.",
448
+    "‘Of course,’ the Dodo replied very gravely. ‘What else have you got in",
449
+    "your pocket?’ he went on, turning to Alice.",
450
+    "‘Only a thimble,’ said Alice sadly.",
451
+    "‘Hand it over here,’ said the Dodo.",
452
+    "Then they all crowded round her once more, while the Dodo solemnly",
453
+    "presented the thimble, saying ‘We beg your acceptance of this elegant",
454
+    "thimble’; and, when it had finished this short speech, they all cheered.",
455
+    "Alice thought the whole thing very absurd, but they all looked so grave",
456
+    "that she did not dare to laugh; and, as she could not think of anything",
457
+    "to say, she simply bowed, and took the thimble, looking as solemn as she",
458
+    "could.",
459
+    "The next thing was to eat the comfits: this caused some noise and",
460
+    "confusion, as the large birds complained that they could not taste",
461
+    "theirs, and the small ones choked and had to be patted on the back.",
462
+    "However, it was over at last, and they sat down again in a ring, and",
463
+    "begged the Mouse to tell them something more.",
464
+    "‘You promised to tell me your history, you know,’ said Alice, ‘and why",
465
+    "it is you hate--C and D,’ she added in a whisper, half afraid that it",
466
+    "would be offended again.",
467
+    "‘Mine is a long and a sad tale!’ said the Mouse, turning to Alice, and",
468
+    "sighing.",
469
+    "‘It IS a long tail, certainly,’ said Alice, looking down with wonder at",
470
+    "the Mouse’s tail; ‘but why do you call it sad?’ And she kept on puzzling",
471
+    "about it while the Mouse was speaking, so that her idea of the tale was",
472
+    "something like this:--",
473
+    "         ‘Fury said to a",
474
+    "         mouse, That he",
475
+    "        met in the",
476
+    "       house,",
477
+    "     “Let us",
478
+    "      both go to",
479
+    "       law: I will",
480
+    "        prosecute",
481
+    "         YOU.--Come,",
482
+    "           I’ll take no",
483
+    "           denial; We",
484
+    "          must have a",
485
+    "        trial: For",
486
+    "      really this",
487
+    "     morning I’ve",
488
+    "    nothing",
489
+    "    to do.”",
490
+    "      Said the",
491
+    "      mouse to the",
492
+    "       cur, “Such",
493
+    "        a trial,",
494
+    "         dear Sir,",
495
+    "            With",
496
+    "          no jury",
497
+    "        or judge,",
498
+    "       would be",
499
+    "      wasting",
500
+    "      our",
501
+    "      breath.”",
502
+    "        “I’ll be",
503
+    "        judge, I’ll",
504
+    "         be jury,”",
505
+    "             Said",
506
+    "         cunning",
507
+    "          old Fury:",
508
+    "          “I’ll",
509
+    "          try the",
510
+    "            whole",
511
+    "            cause,",
512
+    "              and",
513
+    "           condemn",
514
+    "           you",
515
+    "          to",
516
+    "           death.”’",
517
+    "‘You are not attending!’ said the Mouse to Alice severely. ‘What are you",
518
+    "thinking of?’",
519
+    "‘I beg your pardon,’ said Alice very humbly: ‘you had got to the fifth",
520
+    "bend, I think?’",
521
+    "‘I had NOT!’ cried the Mouse, sharply and very angrily.",
522
+    "‘A knot!’ said Alice, always ready to make herself useful, and looking",
523
+    "anxiously about her. ‘Oh, do let me help to undo it!’",
524
+    "‘I shall do nothing of the sort,’ said the Mouse, getting up and walking",
525
+    "away. ‘You insult me by talking such nonsense!’",
526
+    "‘I didn’t mean it!’ pleaded poor Alice. ‘But you’re so easily offended,",
527
+    "you know!’",
528
+    "The Mouse only growled in reply.",
529
+    "‘Please come back and finish your story!’ Alice called after it; and the",
530
+    "others all joined in chorus, ‘Yes, please do!’ but the Mouse only shook",
531
+    "its head impatiently, and walked a little quicker.",
532
+    "‘What a pity it wouldn’t stay!’ sighed the Lory, as soon as it was quite",
533
+    "out of sight; and an old Crab took the opportunity of saying to her",
534
+    "daughter ‘Ah, my dear! Let this be a lesson to you never to lose",
535
+    "YOUR temper!’ ‘Hold your tongue, Ma!’ said the young Crab, a little",
536
+    "snappishly. ‘You’re enough to try the patience of an oyster!’",
537
+    "‘I wish I had our Dinah here, I know I do!’ said Alice aloud, addressing",
538
+    "nobody in particular. ‘She’d soon fetch it back!’",
539
+    "‘And who is Dinah, if I might venture to ask the question?’ said the",
540
+    "Lory.",
541
+    "Alice replied eagerly, for she was always ready to talk about her pet:",
542
+    "‘Dinah’s our cat. And she’s such a capital one for catching mice you",
543
+    "can’t think! And oh, I wish you could see her after the birds! Why,",
544
+    "she’ll eat a little bird as soon as look at it!’",
545
+    "This speech caused a remarkable sensation among the party. Some of the",
546
+    "birds hurried off at once: one old Magpie began wrapping itself up very",
547
+    "carefully, remarking, ‘I really must be getting home; the night-air",
548
+    "doesn’t suit my throat!’ and a Canary called out in a trembling voice to",
549
+    "its children, ‘Come away, my dears! It’s high time you were all in bed!’",
550
+    "On various pretexts they all moved off, and Alice was soon left alone.",
551
+    "‘I wish I hadn’t mentioned Dinah!’ she said to herself in a melancholy",
552
+    "tone. ‘Nobody seems to like her, down here, and I’m sure she’s the best",
553
+    "cat in the world! Oh, my dear Dinah! I wonder if I shall ever see you",
554
+    "any more!’ And here poor Alice began to cry again, for she felt very",
555
+    "lonely and low-spirited. In a little while, however, she again heard",
556
+    "a little pattering of footsteps in the distance, and she looked up",
557
+    "eagerly, half hoping that the Mouse had changed his mind, and was coming",
558
+    "back to finish his story.",
559
+    "CHAPTER IV. The Rabbit Sends in a Little Bill",
560
+    "It was the White Rabbit, trotting slowly back again, and looking",
561
+    "anxiously about as it went, as if it had lost something; and she heard",
562
+    "it muttering to itself ‘The Duchess! The Duchess! Oh my dear paws! Oh",
563
+    "my fur and whiskers! She’ll get me executed, as sure as ferrets are",
564
+    "ferrets! Where CAN I have dropped them, I wonder?’ Alice guessed in a",
565
+    "moment that it was looking for the fan and the pair of white kid gloves,",
566
+    "and she very good-naturedly began hunting about for them, but they were",
567
+    "nowhere to be seen--everything seemed to have changed since her swim in",
568
+    "the pool, and the great hall, with the glass table and the little door,",
569
+    "had vanished completely.",
570
+    "Very soon the Rabbit noticed Alice, as she went hunting about, and",
571
+    "called out to her in an angry tone, ‘Why, Mary Ann, what ARE you doing",
572
+    "out here? Run home this moment, and fetch me a pair of gloves and a fan!",
573
+    "Quick, now!’ And Alice was so much frightened that she ran off at once",
574
+    "in the direction it pointed to, without trying to explain the mistake it",
575
+    "had made.",
576
+    "‘He took me for his housemaid,’ she said to herself as she ran. ‘How",
577
+    "surprised he’ll be when he finds out who I am! But I’d better take him",
578
+    "his fan and gloves--that is, if I can find them.’ As she said this, she",
579
+    "came upon a neat little house, on the door of which was a bright brass",
580
+    "plate with the name ‘W. RABBIT’ engraved upon it. She went in without",
581
+    "knocking, and hurried upstairs, in great fear lest she should meet the",
582
+    "real Mary Ann, and be turned out of the house before she had found the",
583
+    "fan and gloves.",
584
+    "‘How queer it seems,’ Alice said to herself, ‘to be going messages for",
585
+    "a rabbit! I suppose Dinah’ll be sending me on messages next!’ And she",
586
+    "began fancying the sort of thing that would happen: ‘“Miss Alice! Come",
587
+    "here directly, and get ready for your walk!” “Coming in a minute,",
588
+    "nurse! But I’ve got to see that the mouse doesn’t get out.” Only I don’t",
589
+    "think,’ Alice went on, ‘that they’d let Dinah stop in the house if it",
590
+    "began ordering people about like that!’",
591
+    "By this time she had found her way into a tidy little room with a table",
592
+    "in the window, and on it (as she had hoped) a fan and two or three pairs",
593
+    "of tiny white kid gloves: she took up the fan and a pair of the gloves,",
594
+    "and was just going to leave the room, when her eye fell upon a little",
595
+    "bottle that stood near the looking-glass. There was no label this time",
596
+    "with the words ‘DRINK ME,’ but nevertheless she uncorked it and put it",
597
+    "to her lips. ‘I know SOMETHING interesting is sure to happen,’ she said",
598
+    "to herself, ‘whenever I eat or drink anything; so I’ll just see what",
599
+    "this bottle does. I do hope it’ll make me grow large again, for really",
600
+    "I’m quite tired of being such a tiny little thing!’",
601
+    "It did so indeed, and much sooner than she had expected: before she had",
602
+    "drunk half the bottle, she found her head pressing against the ceiling,",
603
+    "and had to stoop to save her neck from being broken. She hastily put",
604
+    "down the bottle, saying to herself ‘That’s quite enough--I hope I shan’t",
605
+    "grow any more--As it is, I can’t get out at the door--I do wish I hadn’t",
606
+    "drunk quite so much!’",
607
+    "Alas! it was too late to wish that! She went on growing, and growing,",
608
+    "and very soon had to kneel down on the floor: in another minute there",
609
+    "was not even room for this, and she tried the effect of lying down with",
610
+    "one elbow against the door, and the other arm curled round her head.",
611
+    "Still she went on growing, and, as a last resource, she put one arm out",
612
+    "of the window, and one foot up the chimney, and said to herself ‘Now I",
613
+    "can do no more, whatever happens. What WILL become of me?’",
614
+    "Luckily for Alice, the little magic bottle had now had its full effect,",
615
+    "and she grew no larger: still it was very uncomfortable, and, as there",
616
+    "seemed to be no sort of chance of her ever getting out of the room",
617
+    "again, no wonder she felt unhappy.",
618
+    "‘It was much pleasanter at home,’ thought poor Alice, ‘when one wasn’t",
619
+    "always growing larger and smaller, and being ordered about by mice and",
620
+    "rabbits. I almost wish I hadn’t gone down that rabbit-hole--and yet--and",
621
+    "yet--it’s rather curious, you know, this sort of life! I do wonder what",
622
+    "CAN have happened to me! When I used to read fairy-tales, I fancied that",
623
+    "kind of thing never happened, and now here I am in the middle of one!",
624
+    "There ought to be a book written about me, that there ought! And when I",
625
+    "grow up, I’ll write one--but I’m grown up now,’ she added in a sorrowful",
626
+    "tone; ‘at least there’s no room to grow up any more HERE.’",
627
+    "‘But then,’ thought Alice, ‘shall I NEVER get any older than I am",
628
+    "now? That’ll be a comfort, one way--never to be an old woman--but",
629
+    "then--always to have lessons to learn! Oh, I shouldn’t like THAT!’",
630
+    "‘Oh, you foolish Alice!’ she answered herself. ‘How can you learn",
631
+    "lessons in here? Why, there’s hardly room for YOU, and no room at all",
632
+    "for any lesson-books!’",
633
+    "And so she went on, taking first one side and then the other, and making",
634
+    "quite a conversation of it altogether; but after a few minutes she heard",
635
+    "a voice outside, and stopped to listen.",
636
+    "‘Mary Ann! Mary Ann!’ said the voice. ‘Fetch me my gloves this moment!’",
637
+    "Then came a little pattering of feet on the stairs. Alice knew it was",
638
+    "the Rabbit coming to look for her, and she trembled till she shook the",
639
+    "house, quite forgetting that she was now about a thousand times as large",
640
+    "as the Rabbit, and had no reason to be afraid of it.",
641
+    "Presently the Rabbit came up to the door, and tried to open it; but, as",
642
+    "the door opened inwards, and Alice’s elbow was pressed hard against it,",
643
+    "that attempt proved a failure. Alice heard it say to itself ‘Then I’ll",
644
+    "go round and get in at the window.’",
645
+    "‘THAT you won’t’ thought Alice, and, after waiting till she fancied",
646
+    "she heard the Rabbit just under the window, she suddenly spread out her",
647
+    "hand, and made a snatch in the air. She did not get hold of anything,",
648
+    "but she heard a little shriek and a fall, and a crash of broken glass,",
649
+    "from which she concluded that it was just possible it had fallen into a",
650
+    "cucumber-frame, or something of the sort.",
651
+    "Next came an angry voice--the Rabbit’s--‘Pat! Pat! Where are you?’ And",
652
+    "then a voice she had never heard before, ‘Sure then I’m here! Digging",
653
+    "for apples, yer honour!’",
654
+    "‘Digging for apples, indeed!’ said the Rabbit angrily. ‘Here! Come and",
655
+    "help me out of THIS!’ (Sounds of more broken glass.)",
656
+    "‘Now tell me, Pat, what’s that in the window?’",
657
+    "‘Sure, it’s an arm, yer honour!’ (He pronounced it ‘arrum.’)",
658
+    "‘An arm, you goose! Who ever saw one that size? Why, it fills the whole",
659
+    "window!’",
660
+    "‘Sure, it does, yer honour: but it’s an arm for all that.’",
661
+    "‘Well, it’s got no business there, at any rate: go and take it away!’",
662
+    "There was a long silence after this, and Alice could only hear whispers",
663
+    "now and then; such as, ‘Sure, I don’t like it, yer honour, at all, at",
664
+    "all!’ ‘Do as I tell you, you coward!’ and at last she spread out her",
665
+    "hand again, and made another snatch in the air. This time there were",
666
+    "TWO little shrieks, and more sounds of broken glass. ‘What a number of",
667
+    "cucumber-frames there must be!’ thought Alice. ‘I wonder what they’ll do",
668
+    "next! As for pulling me out of the window, I only wish they COULD! I’m",
669
+    "sure I don’t want to stay in here any longer!’",
670
+    "She waited for some time without hearing anything more: at last came a",
671
+    "rumbling of little cartwheels, and the sound of a good many voices",
672
+    "all talking together: she made out the words: ‘Where’s the other",
673
+    "ladder?--Why, I hadn’t to bring but one; Bill’s got the other--Bill!",
674
+    "fetch it here, lad!--Here, put ‘em up at this corner--No, tie ‘em",
675
+    "together first--they don’t reach half high enough yet--Oh! they’ll",
676
+    "do well enough; don’t be particular--Here, Bill! catch hold of this",
677
+    "rope--Will the roof bear?--Mind that loose slate--Oh, it’s coming",
678
+    "down! Heads below!’ (a loud crash)--‘Now, who did that?--It was Bill, I",
679
+    "fancy--Who’s to go down the chimney?--Nay, I shan’t! YOU do it!--That I",
680
+    "won’t, then!--Bill’s to go down--Here, Bill! the master says you’re to",
681
+    "go down the chimney!’",
682
+    "‘Oh! So Bill’s got to come down the chimney, has he?’ said Alice to",
683
+    "herself. ‘Shy, they seem to put everything upon Bill! I wouldn’t be in",
684
+    "Bill’s place for a good deal: this fireplace is narrow, to be sure; but",
685
+    "I THINK I can kick a little!’",
686
+    "She drew her foot as far down the chimney as she could, and waited",
687
+    "till she heard a little animal (she couldn’t guess of what sort it was)",
688
+    "scratching and scrambling about in the chimney close above her: then,",
689
+    "saying to herself ‘This is Bill,’ she gave one sharp kick, and waited to",
690
+    "see what would happen next.",
691
+    "The first thing she heard was a general chorus of ‘There goes Bill!’",
692
+    "then the Rabbit’s voice along--‘Catch him, you by the hedge!’ then",
693
+    "silence, and then another confusion of voices--‘Hold up his head--Brandy",
694
+    "now--Don’t choke him--How was it, old fellow? What happened to you? Tell",
695
+    "us all about it!’",
696
+    "Last came a little feeble, squeaking voice, [‘That’s Bill,’ thought",
697
+    "Alice,) ‘Well, I hardly know--No more, thank ye; I’m better now--but I’m",
698
+    "a deal too flustered to tell you--all I know is, something comes at me",
699
+    "like a Jack-in-the-box, and up I goes like a sky-rocket!’",
700
+    "‘So you did, old fellow!’ said the others.",
701
+    "‘We must burn the house down!’ said the Rabbit’s voice; and Alice called",
702
+    "out as loud as she could, ‘If you do. I’ll set Dinah at you!’",
703
+    "There was a dead silence instantly, and Alice thought to herself, ‘I",
704
+    "wonder what they WILL do next! If they had any sense, they’d take the",
705
+    "roof off.’ After a minute or two, they began moving about again, and",
706
+    "Alice heard the Rabbit say, ‘A barrowful will do, to begin with.’",
707
+    "‘A barrowful of WHAT?’ thought Alice; but she had not long to doubt,",
708
+    "for the next moment a shower of little pebbles came rattling in at the",
709
+    "window, and some of them hit her in the face. ‘I’ll put a stop to this,’",
710
+    "she said to herself, and shouted out, ‘You’d better not do that again!’",
711
+    "which produced another dead silence.",
712
+    "Alice noticed with some surprise that the pebbles were all turning into",
713
+    "little cakes as they lay on the floor, and a bright idea came into her",
714
+    "head. ‘If I eat one of these cakes,’ she thought, ‘it’s sure to make",
715
+    "SOME change in my size; and as it can’t possibly make me larger, it must",
716
+    "make me smaller, I suppose.’",
717
+    "So she swallowed one of the cakes, and was delighted to find that she",
718
+    "began shrinking directly. As soon as she was small enough to get through",
719
+    "the door, she ran out of the house, and found quite a crowd of little",
720
+    "animals and birds waiting outside. The poor little Lizard, Bill, was",
721
+    "in the middle, being held up by two guinea-pigs, who were giving it",
722
+    "something out of a bottle. They all made a rush at Alice the moment she",
723
+    "appeared; but she ran off as hard as she could, and soon found herself",
724
+    "safe in a thick wood.",
725
+    "‘The first thing I’ve got to do,’ said Alice to herself, as she wandered",
726
+    "about in the wood, ‘is to grow to my right size again; and the second",
727
+    "thing is to find my way into that lovely garden. I think that will be",
728
+    "the best plan.’",
729
+    "It sounded an excellent plan, no doubt, and very neatly and simply",
730
+    "arranged; the only difficulty was, that she had not the smallest idea",
731
+    "how to set about it; and while she was peering about anxiously among",
732
+    "the trees, a little sharp bark just over her head made her look up in a",
733
+    "great hurry.",
734
+    "An enormous puppy was looking down at her with large round eyes, and",
735
+    "feebly stretching out one paw, trying to touch her. ‘Poor little thing!’",
736
+    "said Alice, in a coaxing tone, and she tried hard to whistle to it; but",
737
+    "she was terribly frightened all the time at the thought that it might be",
738
+    "hungry, in which case it would be very likely to eat her up in spite of",
739
+    "all her coaxing.",
740
+    "Hardly knowing what she did, she picked up a little bit of stick, and",
741
+    "held it out to the puppy; whereupon the puppy jumped into the air off",
742
+    "all its feet at once, with a yelp of delight, and rushed at the stick,",
743
+    "and made believe to worry it; then Alice dodged behind a great thistle,",
744
+    "to keep herself from being run over; and the moment she appeared on the",
745
+    "other side, the puppy made another rush at the stick, and tumbled head",
746
+    "over heels in its hurry to get hold of it; then Alice, thinking it was",
747
+    "very like having a game of play with a cart-horse, and expecting every",
748
+    "moment to be trampled under its feet, ran round the thistle again; then",
749
+    "the puppy began a series of short charges at the stick, running a very",
750
+    "little way forwards each time and a long way back, and barking hoarsely",
751
+    "all the while, till at last it sat down a good way off, panting, with",
752
+    "its tongue hanging out of its mouth, and its great eyes half shut.",
753
+    "This seemed to Alice a good opportunity for making her escape; so she",
754
+    "set off at once, and ran till she was quite tired and out of breath, and",
755
+    "till the puppy’s bark sounded quite faint in the distance.",
756
+    "‘And yet what a dear little puppy it was!’ said Alice, as she leant",
757
+    "against a buttercup to rest herself, and fanned herself with one of the",
758
+    "leaves: ‘I should have liked teaching it tricks very much, if--if I’d",
759
+    "only been the right size to do it! Oh dear! I’d nearly forgotten that",
760
+    "I’ve got to grow up again! Let me see--how IS it to be managed? I",
761
+    "suppose I ought to eat or drink something or other; but the great",
762
+    "question is, what?’",
763
+    "The great question certainly was, what? Alice looked all round her at",
764
+    "the flowers and the blades of grass, but she did not see anything that",
765
+    "looked like the right thing to eat or drink under the circumstances.",
766
+    "There was a large mushroom growing near her, about the same height as",
767
+    "herself; and when she had looked under it, and on both sides of it, and",
768
+    "behind it, it occurred to her that she might as well look and see what",
769
+    "was on the top of it.",
770
+    "She stretched herself up on tiptoe, and peeped over the edge of the",
771
+    "mushroom, and her eyes immediately met those of a large caterpillar,",
772
+    "that was sitting on the top with its arms folded, quietly smoking a long",
773
+    "hookah, and taking not the smallest notice of her or of anything else.",
774
+    "CHAPTER V. Advice from a Caterpillar",
775
+    "The Caterpillar and Alice looked at each other for some time in silence:",
776
+    "at last the Caterpillar took the hookah out of its mouth, and addressed",
777
+    "her in a languid, sleepy voice.",
778
+    "‘Who are YOU?’ said the Caterpillar.",
779
+    "This was not an encouraging opening for a conversation. Alice replied,",
780
+    "rather shyly, ‘I--I hardly know, sir, just at present--at least I know",
781
+    "who I WAS when I got up this morning, but I think I must have been",
782
+    "changed several times since then.’",
783
+    "‘What do you mean by that?’ said the Caterpillar sternly. ‘Explain",
784
+    "yourself!’",
785
+    "‘I can’t explain MYSELF, I’m afraid, sir’ said Alice, ‘because I’m not",
786
+    "myself, you see.’",
787
+    "‘I don’t see,’ said the Caterpillar.",
788
+    "‘I’m afraid I can’t put it more clearly,’ Alice replied very politely,",
789
+    "‘for I can’t understand it myself to begin with; and being so many",
790
+    "different sizes in a day is very confusing.’",
791
+    "‘It isn’t,’ said the Caterpillar.",
792
+    "‘Well, perhaps you haven’t found it so yet,’ said Alice; ‘but when you",
793
+    "have to turn into a chrysalis--you will some day, you know--and then",
794
+    "after that into a butterfly, I should think you’ll feel it a little",
795
+    "queer, won’t you?’",
796
+    "‘Not a bit,’ said the Caterpillar.",
797
+    "‘Well, perhaps your feelings may be different,’ said Alice; ‘all I know",
798
+    "is, it would feel very queer to ME.’",
799
+    "‘You!’ said the Caterpillar contemptuously. ‘Who are YOU?’",
800
+    "Which brought them back again to the beginning of the conversation.",
801
+    "Alice felt a little irritated at the Caterpillar’s making such VERY",
802
+    "short remarks, and she drew herself up and said, very gravely, ‘I think,",
803
+    "you ought to tell me who YOU are, first.’",
804
+    "‘Why?’ said the Caterpillar.",
805
+    "Here was another puzzling question; and as Alice could not think of any",
806
+    "good reason, and as the Caterpillar seemed to be in a VERY unpleasant",
807
+    "state of mind, she turned away.",
808
+    "‘Come back!’ the Caterpillar called after her. ‘I’ve something important",
809
+    "to say!’",
810
+    "This sounded promising, certainly: Alice turned and came back again.",
811
+    "‘Keep your temper,’ said the Caterpillar.",
812
+    "‘Is that all?’ said Alice, swallowing down her anger as well as she",
813
+    "could.",
814
+    "‘No,’ said the Caterpillar.",
815
+    "Alice thought she might as well wait, as she had nothing else to do, and",
816
+    "perhaps after all it might tell her something worth hearing. For some",
817
+    "minutes it puffed away without speaking, but at last it unfolded its",
818
+    "arms, took the hookah out of its mouth again, and said, ‘So you think",
819
+    "you’re changed, do you?’",
820
+    "‘I’m afraid I am, sir,’ said Alice; ‘I can’t remember things as I",
821
+    "used--and I don’t keep the same size for ten minutes together!’",
822
+    "‘Can’t remember WHAT things?’ said the Caterpillar.",
823
+    "‘Well, I’ve tried to say “HOW DOTH THE LITTLE BUSY BEE,” but it all came",
824
+    "different!’ Alice replied in a very melancholy voice.",
825
+    "‘Repeat, “YOU ARE OLD, FATHER WILLIAM,”’ said the Caterpillar.",
826
+    "Alice folded her hands, and began:--",
827
+    "   ‘You are old, Father William,’ the young man said,",
828
+    "    ‘And your hair has become very white;",
829
+    "   And yet you incessantly stand on your head--",
830
+    "    Do you think, at your age, it is right?’",
831
+    "   ‘In my youth,’ Father William replied to his son,",
832
+    "    ‘I feared it might injure the brain;",
833
+    "   But, now that I’m perfectly sure I have none,",
834
+    "    Why, I do it again and again.’",
835
+    "   ‘You are old,’ said the youth, ‘as I mentioned before,",
836
+    "    And have grown most uncommonly fat;",
837
+    "   Yet you turned a back-somersault in at the door--",
838
+    "    Pray, what is the reason of that?’",
839
+    "   ‘In my youth,’ said the sage, as he shook his grey locks,",
840
+    "    ‘I kept all my limbs very supple",
841
+    "   By the use of this ointment--one shilling the box--",
842
+    "    Allow me to sell you a couple?’",
843
+    "   ‘You are old,’ said the youth, ‘and your jaws are too weak",
844
+    "    For anything tougher than suet;",
845
+    "   Yet you finished the goose, with the bones and the beak--",
846
+    "    Pray how did you manage to do it?’",
847
+    "   ‘In my youth,’ said his father, ‘I took to the law,",
848
+    "    And argued each case with my wife;",
849
+    "   And the muscular strength, which it gave to my jaw,",
850
+    "    Has lasted the rest of my life.’",
851
+    "   ‘You are old,’ said the youth, ‘one would hardly suppose",
852
+    "    That your eye was as steady as ever;",
853
+    "   Yet you balanced an eel on the end of your nose--",
854
+    "    What made you so awfully clever?’",
855
+    "   ‘I have answered three questions, and that is enough,’",
856
+    "    Said his father; ‘don’t give yourself airs!",
857
+    "   Do you think I can listen all day to such stuff?",
858
+    "    Be off, or I’ll kick you down stairs!’",
859
+    "‘That is not said right,’ said the Caterpillar.",
860
+    "‘Not QUITE right, I’m afraid,’ said Alice, timidly; ‘some of the words",
861
+    "have got altered.’",
862
+    "‘It is wrong from beginning to end,’ said the Caterpillar decidedly, and",
863
+    "there was silence for some minutes.",
864
+    "The Caterpillar was the first to speak.",
865
+    "‘What size do you want to be?’ it asked.",
866
+    "‘Oh, I’m not particular as to size,’ Alice hastily replied; ‘only one",
867
+    "doesn’t like changing so often, you know.’",
868
+    "‘I DON’T know,’ said the Caterpillar.",
869
+    "Alice said nothing: she had never been so much contradicted in her life",
870
+    "before, and she felt that she was losing her temper.",
871
+    "‘Are you content now?’ said the Caterpillar.",
872
+    "‘Well, I should like to be a LITTLE larger, sir, if you wouldn’t mind,’",
873
+    "said Alice: ‘three inches is such a wretched height to be.’",
874
+    "‘It is a very good height indeed!’ said the Caterpillar angrily, rearing",
875
+    "itself upright as it spoke (it was exactly three inches high).",
876
+    "‘But I’m not used to it!’ pleaded poor Alice in a piteous tone. And",
877
+    "she thought of herself, ‘I wish the creatures wouldn’t be so easily",
878
+    "offended!’",
879
+    "‘You’ll get used to it in time,’ said the Caterpillar; and it put the",
880
+    "hookah into its mouth and began smoking again.",
881
+    "This time Alice waited patiently until it chose to speak again. In",
882
+    "a minute or two the Caterpillar took the hookah out of its mouth",
883
+    "and yawned once or twice, and shook itself. Then it got down off the",
884
+    "mushroom, and crawled away in the grass, merely remarking as it went,",
885
+    "‘One side will make you grow taller, and the other side will make you",
886
+    "grow shorter.’",
887
+    "‘One side of WHAT? The other side of WHAT?’ thought Alice to herself.",
888
+    "‘Of the mushroom,’ said the Caterpillar, just as if she had asked it",
889
+    "aloud; and in another moment it was out of sight.",
890
+    "Alice remained looking thoughtfully at the mushroom for a minute, trying",
891
+    "to make out which were the two sides of it; and as it was perfectly",
892
+    "round, she found this a very difficult question. However, at last she",
893
+    "stretched her arms round it as far as they would go, and broke off a bit",
894
+    "of the edge with each hand.",
895
+    "‘And now which is which?’ she said to herself, and nibbled a little of",
896
+    "the right-hand bit to try the effect: the next moment she felt a violent",
897
+    "blow underneath her chin: it had struck her foot!",
898
+    "She was a good deal frightened by this very sudden change, but she felt",
899
+    "that there was no time to be lost, as she was shrinking rapidly; so she",
900
+    "set to work at once to eat some of the other bit. Her chin was pressed",
901
+    "so closely against her foot, that there was hardly room to open her",
902
+    "mouth; but she did it at last, and managed to swallow a morsel of the",
903
+    "lefthand bit.",
904
+    "  *    *    *    *    *    *    *",
905
+    "    *    *    *    *    *    *",
906
+    "  *    *    *    *    *    *    *",
907
+    "‘Come, my head’s free at last!’ said Alice in a tone of delight, which",
908
+    "changed into alarm in another moment, when she found that her shoulders",
909
+    "were nowhere to be found: all she could see, when she looked down, was",
910
+    "an immense length of neck, which seemed to rise like a stalk out of a",
911
+    "sea of green leaves that lay far below her.",
912
+    "‘What CAN all that green stuff be?’ said Alice. ‘And where HAVE my",
913
+    "shoulders got to? And oh, my poor hands, how is it I can’t see you?’",
914
+    "She was moving them about as she spoke, but no result seemed to follow,",
915
+    "except a little shaking among the distant green leaves.",
916
+    "As there seemed to be no chance of getting her hands up to her head, she",
917
+    "tried to get her head down to them, and was delighted to find that her",
918
+    "neck would bend about easily in any direction, like a serpent. She had",
919
+    "just succeeded in curving it down into a graceful zigzag, and was going",
920
+    "to dive in among the leaves, which she found to be nothing but the tops",
921
+    "of the trees under which she had been wandering, when a sharp hiss made",
922
+    "her draw back in a hurry: a large pigeon had flown into her face, and",
923
+    "was beating her violently with its wings.",
924
+    "‘Serpent!’ screamed the Pigeon.",
925
+    "‘I’m NOT a serpent!’ said Alice indignantly. ‘Let me alone!’",
926
+    "‘Serpent, I say again!’ repeated the Pigeon, but in a more subdued tone,",
927
+    "and added with a kind of sob, ‘I’ve tried every way, and nothing seems",
928
+    "to suit them!’",
929
+    "‘I haven’t the least idea what you’re talking about,’ said Alice.",
930
+    "‘I’ve tried the roots of trees, and I’ve tried banks, and I’ve tried",
931
+    "hedges,’ the Pigeon went on, without attending to her; ‘but those",
932
+    "serpents! There’s no pleasing them!’",
933
+    "Alice was more and more puzzled, but she thought there was no use in",
934
+    "saying anything more till the Pigeon had finished.",
935
+    "‘As if it wasn’t trouble enough hatching the eggs,’ said the Pigeon;",
936
+    "‘but I must be on the look-out for serpents night and day! Why, I",
937
+    "haven’t had a wink of sleep these three weeks!’",
938
+    "‘I’m very sorry you’ve been annoyed,’ said Alice, who was beginning to",
939
+    "see its meaning.",
940
+    "‘And just as I’d taken the highest tree in the wood,’ continued the",
941
+    "Pigeon, raising its voice to a shriek, ‘and just as I was thinking I",
942
+    "should be free of them at last, they must needs come wriggling down from",
943
+    "the sky! Ugh, Serpent!’",
944
+    "‘But I’m NOT a serpent, I tell you!’ said Alice. ‘I’m a--I’m a--’",
945
+    "‘Well! WHAT are you?’ said the Pigeon. ‘I can see you’re trying to",
946
+    "invent something!’",
947
+    "‘I--I’m a little girl,’ said Alice, rather doubtfully, as she remembered",
948
+    "the number of changes she had gone through that day.",
949
+    "‘A likely story indeed!’ said the Pigeon in a tone of the deepest",
950
+    "contempt. ‘I’ve seen a good many little girls in my time, but never ONE",
951
+    "with such a neck as that! No, no! You’re a serpent; and there’s no use",
952
+    "denying it. I suppose you’ll be telling me next that you never tasted an",
953
+    "egg!’",
954
+    "‘I HAVE tasted eggs, certainly,’ said Alice, who was a very truthful",
955
+    "child; ‘but little girls eat eggs quite as much as serpents do, you",
956
+    "know.’",
957
+    "‘I don’t believe it,’ said the Pigeon; ‘but if they do, why then they’re",
958
+    "a kind of serpent, that’s all I can say.’",
959
+    "This was such a new idea to Alice, that she was quite silent for a",
960
+    "minute or two, which gave the Pigeon the opportunity of adding, ‘You’re",
961
+    "looking for eggs, I know THAT well enough; and what does it matter to me",
962
+    "whether you’re a little girl or a serpent?’",
963
+    "‘It matters a good deal to ME,’ said Alice hastily; ‘but I’m not looking",
964
+    "for eggs, as it happens; and if I was, I shouldn’t want YOURS: I don’t",
965
+    "like them raw.’",
966
+    "‘Well, be off, then!’ said the Pigeon in a sulky tone, as it settled",
967
+    "down again into its nest. Alice crouched down among the trees as well as",
968
+    "she could, for her neck kept getting entangled among the branches, and",
969
+    "every now and then she had to stop and untwist it. After a while she",
970
+    "remembered that she still held the pieces of mushroom in her hands, and",
971
+    "she set to work very carefully, nibbling first at one and then at the",
972
+    "other, and growing sometimes taller and sometimes shorter, until she had",
973
+    "succeeded in bringing herself down to her usual height.",
974
+    "It was so long since she had been anything near the right size, that it",
975
+    "felt quite strange at first; but she got used to it in a few minutes,",
976
+    "and began talking to herself, as usual. ‘Come, there’s half my plan done",
977
+    "now! How puzzling all these changes are! I’m never sure what I’m going",
978
+    "to be, from one minute to another! However, I’ve got back to my right",
979
+    "size: the next thing is, to get into that beautiful garden--how IS that",
980
+    "to be done, I wonder?’ As she said this, she came suddenly upon an open",
981
+    "place, with a little house in it about four feet high. ‘Whoever lives",
982
+    "there,’ thought Alice, ‘it’ll never do to come upon them THIS size: why,",
983
+    "I should frighten them out of their wits!’ So she began nibbling at the",
984
+    "righthand bit again, and did not venture to go near the house till she",
985
+    "had brought herself down to nine inches high.",
986
+    "CHAPTER VI. Pig and Pepper",
987
+    "For a minute or two she stood looking at the house, and wondering what",
988
+    "to do next, when suddenly a footman in livery came running out of the",
989
+    "wood--(she considered him to be a footman because he was in livery:",
990
+    "otherwise, judging by his face only, she would have called him a",
991
+    "fish)--and rapped loudly at the door with his knuckles. It was opened",
992
+    "by another footman in livery, with a round face, and large eyes like a",
993
+    "frog; and both footmen, Alice noticed, had powdered hair that curled all",
994
+    "over their heads. She felt very curious to know what it was all about,",
995
+    "and crept a little way out of the wood to listen.",
996
+    "The Fish-Footman began by producing from under his arm a great letter,",
997
+    "nearly as large as himself, and this he handed over to the other,",
998
+    "saying, in a solemn tone, ‘For the Duchess. An invitation from the Queen",
999
+    "to play croquet.’ The Frog-Footman repeated, in the same solemn tone,",
1000
+    "only changing the order of the words a little, ‘From the Queen. An",
1001
+    "invitation for the Duchess to play croquet.’",
1002
+    "Then they both bowed low, and their curls got entangled together.",
1003
+    "Alice laughed so much at this, that she had to run back into the",
1004
+    "wood for fear of their hearing her; and when she next peeped out the",
1005
+    "Fish-Footman was gone, and the other was sitting on the ground near the",
1006
+    "door, staring stupidly up into the sky.",
1007
+    "Alice went timidly up to the door, and knocked.",
1008
+    "‘There’s no sort of use in knocking,’ said the Footman, ‘and that for",
1009
+    "two reasons. First, because I’m on the same side of the door as you",
1010
+    "are; secondly, because they’re making such a noise inside, no one could",
1011
+    "possibly hear you.’ And certainly there was a most extraordinary noise",
1012
+    "going on within--a constant howling and sneezing, and every now and then",
1013
+    "a great crash, as if a dish or kettle had been broken to pieces.",
1014
+    "‘Please, then,’ said Alice, ‘how am I to get in?’",
1015
+    "‘There might be some sense in your knocking,’ the Footman went on",
1016
+    "without attending to her, ‘if we had the door between us. For instance,",
1017
+    "if you were INSIDE, you might knock, and I could let you out, you know.’",
1018
+    "He was looking up into the sky all the time he was speaking, and this",
1019
+    "Alice thought decidedly uncivil. ‘But perhaps he can’t help it,’ she",
1020
+    "said to herself; ‘his eyes are so VERY nearly at the top of his head.",
1021
+    "But at any rate he might answer questions.--How am I to get in?’ she",
1022
+    "repeated, aloud.",
1023
+    "‘I shall sit here,’ the Footman remarked, ‘till tomorrow--’",
1024
+    "At this moment the door of the house opened, and a large plate came",
1025
+    "skimming out, straight at the Footman’s head: it just grazed his nose,",
1026
+    "and broke to pieces against one of the trees behind him.",
1027
+    "‘--or next day, maybe,’ the Footman continued in the same tone, exactly",
1028
+    "as if nothing had happened.",
1029
+    "‘How am I to get in?’ asked Alice again, in a louder tone.",
1030
+    "‘ARE you to get in at all?’ said the Footman. ‘That’s the first",
1031
+    "question, you know.’",
1032
+    "It was, no doubt: only Alice did not like to be told so. ‘It’s really",
1033
+    "dreadful,’ she muttered to herself, ‘the way all the creatures argue.",
1034
+    "It’s enough to drive one crazy!’",
1035
+    "The Footman seemed to think this a good opportunity for repeating his",
1036
+    "remark, with variations. ‘I shall sit here,’ he said, ‘on and off, for",
1037
+    "days and days.’",
1038
+    "‘But what am I to do?’ said Alice.",
1039
+    "‘Anything you like,’ said the Footman, and began whistling.",
1040
+    "‘Oh, there’s no use in talking to him,’ said Alice desperately: ‘he’s",
1041
+    "perfectly idiotic!’ And she opened the door and went in.",
1042
+    "The door led right into a large kitchen, which was full of smoke from",
1043
+    "one end to the other: the Duchess was sitting on a three-legged stool in",
1044
+    "the middle, nursing a baby; the cook was leaning over the fire, stirring",
1045
+    "a large cauldron which seemed to be full of soup.",
1046
+    "‘There’s certainly too much pepper in that soup!’ Alice said to herself,",
1047
+    "as well as she could for sneezing.",
1048
+    "There was certainly too much of it in the air. Even the Duchess",
1049
+    "sneezed occasionally; and as for the baby, it was sneezing and howling",
1050
+    "alternately without a moment’s pause. The only things in the kitchen",
1051
+    "that did not sneeze, were the cook, and a large cat which was sitting on",
1052
+    "the hearth and grinning from ear to ear.",
1053
+    "‘Please would you tell me,’ said Alice, a little timidly, for she was",
1054
+    "not quite sure whether it was good manners for her to speak first, ‘why",
1055
+    "your cat grins like that?’",
1056
+    "‘It’s a Cheshire cat,’ said the Duchess, ‘and that’s why. Pig!’",
1057
+    "She said the last word with such sudden violence that Alice quite",
1058
+    "jumped; but she saw in another moment that it was addressed to the baby,",
1059
+    "and not to her, so she took courage, and went on again:--",
1060
+    "‘I didn’t know that Cheshire cats always grinned; in fact, I didn’t know",
1061
+    "that cats COULD grin.’",
1062
+    "‘They all can,’ said the Duchess; ‘and most of ‘em do.’",
1063
+    "‘I don’t know of any that do,’ Alice said very politely, feeling quite",
1064
+    "pleased to have got into a conversation.",
1065
+    "‘You don’t know much,’ said the Duchess; ‘and that’s a fact.’",
1066
+    "Alice did not at all like the tone of this remark, and thought it would",
1067
+    "be as well to introduce some other subject of conversation. While she",
1068
+    "was trying to fix on one, the cook took the cauldron of soup off the",
1069
+    "fire, and at once set to work throwing everything within her reach at",
1070
+    "the Duchess and the baby--the fire-irons came first; then followed a",
1071
+    "shower of saucepans, plates, and dishes. The Duchess took no notice of",
1072
+    "them even when they hit her; and the baby was howling so much already,",
1073
+    "that it was quite impossible to say whether the blows hurt it or not.",
1074
+    "‘Oh, PLEASE mind what you’re doing!’ cried Alice, jumping up and down in",
1075
+    "an agony of terror. ‘Oh, there goes his PRECIOUS nose’; as an unusually",
1076
+    "large saucepan flew close by it, and very nearly carried it off.",
1077
+    "‘If everybody minded their own business,’ the Duchess said in a hoarse",
1078
+    "growl, ‘the world would go round a deal faster than it does.’",
1079
+    "‘Which would NOT be an advantage,’ said Alice, who felt very glad to get",
1080
+    "an opportunity of showing off a little of her knowledge. ‘Just think of",
1081
+    "what work it would make with the day and night! You see the earth takes",
1082
+    "twenty-four hours to turn round on its axis--’",
1083
+    "‘Talking of axes,’ said the Duchess, ‘chop off her head!’",
1084
+    "Alice glanced rather anxiously at the cook, to see if she meant to take",
1085
+    "the hint; but the cook was busily stirring the soup, and seemed not to",
1086
+    "be listening, so she went on again: ‘Twenty-four hours, I THINK; or is",
1087
+    "it twelve? I--’",
1088
+    "‘Oh, don’t bother ME,’ said the Duchess; ‘I never could abide figures!’",
1089
+    "And with that she began nursing her child again, singing a sort of",
1090
+    "lullaby to it as she did so, and giving it a violent shake at the end of",
1091
+    "every line:",
1092
+    "   ‘Speak roughly to your little boy,",
1093
+    "    And beat him when he sneezes:",
1094
+    "   He only does it to annoy,",
1095
+    "    Because he knows it teases.’",
1096
+    "         CHORUS.",
1097
+    " (In which the cook and the baby joined):--",
1098
+    "       ‘Wow! wow! wow!’",
1099
+    "While the Duchess sang the second verse of the song, she kept tossing",
1100
+    "the baby violently up and down, and the poor little thing howled so,",
1101
+    "that Alice could hardly hear the words:--",
1102
+    "   ‘I speak severely to my boy,",
1103
+    "    I beat him when he sneezes;",
1104
+    "   For he can thoroughly enjoy",
1105
+    "    The pepper when he pleases!’",
1106
+    "         CHORUS.",
1107
+    "       ‘Wow! wow! wow!’",
1108
+    "‘Here! you may nurse it a bit, if you like!’ the Duchess said to Alice,",
1109
+    "flinging the baby at her as she spoke. ‘I must go and get ready to play",
1110
+    "croquet with the Queen,’ and she hurried out of the room. The cook threw",
1111
+    "a frying-pan after her as she went out, but it just missed her.",
1112
+    "Alice caught the baby with some difficulty, as it was a queer-shaped",
1113
+    "little creature, and held out its arms and legs in all directions, ‘just",
1114
+    "like a star-fish,’ thought Alice. The poor little thing was snorting",
1115
+    "like a steam-engine when she caught it, and kept doubling itself up and",
1116
+    "straightening itself out again, so that altogether, for the first minute",
1117
+    "or two, it was as much as she could do to hold it.",
1118
+    "As soon as she had made out the proper way of nursing it, (which was to",
1119
+    "twist it up into a sort of knot, and then keep tight hold of its right",
1120
+    "ear and left foot, so as to prevent its undoing itself,) she carried",
1121
+    "it out into the open air. ‘IF I don’t take this child away with me,’",
1122
+    "thought Alice, ‘they’re sure to kill it in a day or two: wouldn’t it be",
1123
+    "murder to leave it behind?’ She said the last words out loud, and the",
1124
+    "little thing grunted in reply (it had left off sneezing by this time).",
1125
+    "‘Don’t grunt,’ said Alice; ‘that’s not at all a proper way of expressing",
1126
+    "yourself.’",
1127
+    "The baby grunted again, and Alice looked very anxiously into its face to",
1128
+    "see what was the matter with it. There could be no doubt that it had",
1129
+    "a VERY turn-up nose, much more like a snout than a real nose; also its",
1130
+    "eyes were getting extremely small for a baby: altogether Alice did not",
1131
+    "like the look of the thing at all. ‘But perhaps it was only sobbing,’",
1132
+    "she thought, and looked into its eyes again, to see if there were any",
1133
+    "tears.",
1134
+    "No, there were no tears. ‘If you’re going to turn into a pig, my dear,’",
1135
+    "said Alice, seriously, ‘I’ll have nothing more to do with you. Mind",
1136
+    "now!’ The poor little thing sobbed again (or grunted, it was impossible",
1137
+    "to say which), and they went on for some while in silence.",
1138
+    "Alice was just beginning to think to herself, ‘Now, what am I to do with",
1139
+    "this creature when I get it home?’ when it grunted again, so violently,",
1140
+    "that she looked down into its face in some alarm. This time there could",
1141
+    "be NO mistake about it: it was neither more nor less than a pig, and she",
1142
+    "felt that it would be quite absurd for her to carry it further.",
1143
+    "So she set the little creature down, and felt quite relieved to see",
1144
+    "it trot away quietly into the wood. ‘If it had grown up,’ she said",
1145
+    "to herself, ‘it would have made a dreadfully ugly child: but it makes",
1146
+    "rather a handsome pig, I think.’ And she began thinking over other",
1147
+    "children she knew, who might do very well as pigs, and was just saying",
1148
+    "to herself, ‘if one only knew the right way to change them--’ when she",
1149
+    "was a little startled by seeing the Cheshire Cat sitting on a bough of a",
1150
+    "tree a few yards off.",
1151
+    "The Cat only grinned when it saw Alice. It looked good-natured, she",
1152
+    "thought: still it had VERY long claws and a great many teeth, so she",
1153
+    "felt that it ought to be treated with respect.",
1154
+    "‘Cheshire Puss,’ she began, rather timidly, as she did not at all know",
1155
+    "whether it would like the name: however, it only grinned a little wider.",
1156
+    "‘Come, it’s pleased so far,’ thought Alice, and she went on. ‘Would you",
1157
+    "tell me, please, which way I ought to go from here?’",
1158
+    "‘That depends a good deal on where you want to get to,’ said the Cat.",
1159
+    "‘I don’t much care where--’ said Alice.",
1160
+    "‘Then it doesn’t matter which way you go,’ said the Cat.",
1161
+    "‘--so long as I get SOMEWHERE,’ Alice added as an explanation.",
1162
+    "‘Oh, you’re sure to do that,’ said the Cat, ‘if you only walk long",
1163
+    "enough.’",
1164
+    "Alice felt that this could not be denied, so she tried another question.",
1165
+    "‘What sort of people live about here?’",
1166
+    "‘In THAT direction,’ the Cat said, waving its right paw round, ‘lives",
1167
+    "a Hatter: and in THAT direction,’ waving the other paw, ‘lives a March",
1168
+    "Hare. Visit either you like: they’re both mad.’",
1169
+    "‘But I don’t want to go among mad people,’ Alice remarked.",
1170
+    "‘Oh, you can’t help that,’ said the Cat: ‘we’re all mad here. I’m mad.",
1171
+    "You’re mad.’",
1172
+    "‘How do you know I’m mad?’ said Alice.",
1173
+    "‘You must be,’ said the Cat, ‘or you wouldn’t have come here.’",
1174
+    "Alice didn’t think that proved it at all; however, she went on ‘And how",
1175
+    "do you know that you’re mad?’",
1176
+    "‘To begin with,’ said the Cat, ‘a dog’s not mad. You grant that?’",
1177
+    "‘I suppose so,’ said Alice.",
1178
+    "‘Well, then,’ the Cat went on, ‘you see, a dog growls when it’s angry,",
1179
+    "and wags its tail when it’s pleased. Now I growl when I’m pleased, and",
1180
+    "wag my tail when I’m angry. Therefore I’m mad.’",
1181
+    "‘I call it purring, not growling,’ said Alice.",
1182
+    "‘Call it what you like,’ said the Cat. ‘Do you play croquet with the",
1183
+    "Queen to-day?’",
1184
+    "‘I should like it very much,’ said Alice, ‘but I haven’t been invited",
1185
+    "yet.’",
1186
+    "‘You’ll see me there,’ said the Cat, and vanished.",
1187
+    "Alice was not much surprised at this, she was getting so used to queer",
1188
+    "things happening. While she was looking at the place where it had been,",
1189
+    "it suddenly appeared again.",
1190
+    "‘By-the-bye, what became of the baby?’ said the Cat. ‘I’d nearly",
1191
+    "forgotten to ask.’",
1192
+    "‘It turned into a pig,’ Alice quietly said, just as if it had come back",
1193
+    "in a natural way.",
1194
+    "‘I thought it would,’ said the Cat, and vanished again.",
1195
+    "Alice waited a little, half expecting to see it again, but it did not",
1196
+    "appear, and after a minute or two she walked on in the direction in",
1197
+    "which the March Hare was said to live. ‘I’ve seen hatters before,’ she",
1198
+    "said to herself; ‘the March Hare will be much the most interesting, and",
1199
+    "perhaps as this is May it won’t be raving mad--at least not so mad as",
1200
+    "it was in March.’ As she said this, she looked up, and there was the Cat",
1201
+    "again, sitting on a branch of a tree.",
1202
+    "‘Did you say pig, or fig?’ said the Cat.",
1203
+    "‘I said pig,’ replied Alice; ‘and I wish you wouldn’t keep appearing and",
1204
+    "vanishing so suddenly: you make one quite giddy.’",
1205
+    "‘All right,’ said the Cat; and this time it vanished quite slowly,",
1206
+    "beginning with the end of the tail, and ending with the grin, which",
1207
+    "remained some time after the rest of it had gone.",
1208
+    "‘Well! I’ve often seen a cat without a grin,’ thought Alice; ‘but a grin",
1209
+    "without a cat! It’s the most curious thing I ever saw in my life!’",
1210
+    "She had not gone much farther before she came in sight of the house",
1211
+    "of the March Hare: she thought it must be the right house, because the",
1212
+    "chimneys were shaped like ears and the roof was thatched with fur. It",
1213
+    "was so large a house, that she did not like to go nearer till she had",
1214
+    "nibbled some more of the lefthand bit of mushroom, and raised herself to",
1215
+    "about two feet high: even then she walked up towards it rather timidly,",
1216
+    "saying to herself ‘Suppose it should be raving mad after all! I almost",
1217
+    "wish I’d gone to see the Hatter instead!’",
1218
+    "CHAPTER VII. A Mad Tea-Party",
1219
+    "There was a table set out under a tree in front of the house, and the",
1220
+    "March Hare and the Hatter were having tea at it: a Dormouse was sitting",
1221
+    "between them, fast asleep, and the other two were using it as a",
1222
+    "cushion, resting their elbows on it, and talking over its head. ‘Very",
1223
+    "uncomfortable for the Dormouse,’ thought Alice; ‘only, as it’s asleep, I",
1224
+    "suppose it doesn’t mind.’",
1225
+    "The table was a large one, but the three were all crowded together at",
1226
+    "one corner of it: ‘No room! No room!’ they cried out when they saw Alice",
1227
+    "coming. ‘There’s PLENTY of room!’ said Alice indignantly, and she sat",
1228
+    "down in a large arm-chair at one end of the table.",
1229
+    "‘Have some wine,’ the March Hare said in an encouraging tone.",
1230
+    "Alice looked all round the table, but there was nothing on it but tea.",
1231
+    "‘I don’t see any wine,’ she remarked.",
1232
+    "‘There isn’t any,’ said the March Hare.",
1233
+    "‘Then it wasn’t very civil of you to offer it,’ said Alice angrily.",
1234
+    "‘It wasn’t very civil of you to sit down without being invited,’ said",
1235
+    "the March Hare.",
1236
+    "‘I didn’t know it was YOUR table,’ said Alice; ‘it’s laid for a great",
1237
+    "many more than three.’",
1238
+    "‘Your hair wants cutting,’ said the Hatter. He had been looking at Alice",
1239
+    "for some time with great curiosity, and this was his first speech.",
1240
+    "‘You should learn not to make personal remarks,’ Alice said with some",
1241
+    "severity; ‘it’s very rude.’",
1242
+    "The Hatter opened his eyes very wide on hearing this; but all he SAID",
1243
+    "was, ‘Why is a raven like a writing-desk?’",
1244
+    "‘Come, we shall have some fun now!’ thought Alice. ‘I’m glad they’ve",
1245
+    "begun asking riddles.--I believe I can guess that,’ she added aloud.",
1246
+    "‘Do you mean that you think you can find out the answer to it?’ said the",
1247
+    "March Hare.",
1248
+    "‘Exactly so,’ said Alice.",
1249
+    "‘Then you should say what you mean,’ the March Hare went on.",
1250
+    "‘I do,’ Alice hastily replied; ‘at least--at least I mean what I",
1251
+    "say--that’s the same thing, you know.’",
1252
+    "‘Not the same thing a bit!’ said the Hatter. ‘You might just as well say",
1253
+    "that “I see what I eat” is the same thing as “I eat what I see”!’",
1254
+    "‘You might just as well say,’ added the March Hare, ‘that “I like what I",
1255
+    "get” is the same thing as “I get what I like”!’",
1256
+    "‘You might just as well say,’ added the Dormouse, who seemed to be",
1257
+    "talking in his sleep, ‘that “I breathe when I sleep” is the same thing",
1258
+    "as “I sleep when I breathe”!’",
1259
+    "‘It IS the same thing with you,’ said the Hatter, and here the",
1260
+    "conversation dropped, and the party sat silent for a minute, while Alice",
1261
+    "thought over all she could remember about ravens and writing-desks,",
1262
+    "which wasn’t much.",
1263
+    "The Hatter was the first to break the silence. ‘What day of the month",
1264
+    "is it?’ he said, turning to Alice: he had taken his watch out of his",
1265
+    "pocket, and was looking at it uneasily, shaking it every now and then,",
1266
+    "and holding it to his ear.",
1267
+    "Alice considered a little, and then said ‘The fourth.’",
1268
+    "‘Two days wrong!’ sighed the Hatter. ‘I told you butter wouldn’t suit",
1269
+    "the works!’ he added looking angrily at the March Hare.",
1270
+    "‘It was the BEST butter,’ the March Hare meekly replied.",
1271
+    "‘Yes, but some crumbs must have got in as well,’ the Hatter grumbled:",
1272
+    "‘you shouldn’t have put it in with the bread-knife.’",
1273
+    "The March Hare took the watch and looked at it gloomily: then he dipped",
1274
+    "it into his cup of tea, and looked at it again: but he could think of",
1275
+    "nothing better to say than his first remark, ‘It was the BEST butter,",
1276
+    "you know.’",
1277
+    "Alice had been looking over his shoulder with some curiosity. ‘What a",
1278
+    "funny watch!’ she remarked. ‘It tells the day of the month, and doesn’t",
1279
+    "tell what o’clock it is!’",
1280
+    "‘Why should it?’ muttered the Hatter. ‘Does YOUR watch tell you what",
1281
+    "year it is?’",
1282
+    "‘Of course not,’ Alice replied very readily: ‘but that’s because it",
1283
+    "stays the same year for such a long time together.’",
1284
+    "‘Which is just the case with MINE,’ said the Hatter.",
1285
+    "Alice felt dreadfully puzzled. The Hatter’s remark seemed to have no",
1286
+    "sort of meaning in it, and yet it was certainly English. ‘I don’t quite",
1287
+    "understand you,’ she said, as politely as she could.",
1288
+    "‘The Dormouse is asleep again,’ said the Hatter, and he poured a little",
1289
+    "hot tea upon its nose.",
1290
+    "The Dormouse shook its head impatiently, and said, without opening its",
1291
+    "eyes, ‘Of course, of course; just what I was going to remark myself.’",
1292
+    "‘Have you guessed the riddle yet?’ the Hatter said, turning to Alice",
1293
+    "again.",
1294
+    "‘No, I give it up,’ Alice replied: ‘what’s the answer?’",
1295
+    "‘I haven’t the slightest idea,’ said the Hatter.",
1296
+    "‘Nor I,’ said the March Hare.",
1297
+    "Alice sighed wearily. ‘I think you might do something better with the",
1298
+    "time,’ she said, ‘than waste it in asking riddles that have no answers.’",
1299
+    "‘If you knew Time as well as I do,’ said the Hatter, ‘you wouldn’t talk",
1300
+    "about wasting IT. It’s HIM.’",
1301
+    "‘I don’t know what you mean,’ said Alice.",
1302
+    "‘Of course you don’t!’ the Hatter said, tossing his head contemptuously.",
1303
+    "‘I dare say you never even spoke to Time!’",
1304
+    "‘Perhaps not,’ Alice cautiously replied: ‘but I know I have to beat time",
1305
+    "when I learn music.’",
1306
+    "‘Ah! that accounts for it,’ said the Hatter. ‘He won’t stand beating.",
1307
+    "Now, if you only kept on good terms with him, he’d do almost anything",
1308
+    "you liked with the clock. For instance, suppose it were nine o’clock in",
1309
+    "the morning, just time to begin lessons: you’d only have to whisper a",
1310
+    "hint to Time, and round goes the clock in a twinkling! Half-past one,",
1311
+    "time for dinner!’",
1312
+    "[‘I only wish it was,’ the March Hare said to itself in a whisper.)",
1313
+    "‘That would be grand, certainly,’ said Alice thoughtfully: ‘but then--I",
1314
+    "shouldn’t be hungry for it, you know.’",
1315
+    "‘Not at first, perhaps,’ said the Hatter: ‘but you could keep it to",
1316
+    "half-past one as long as you liked.’",
1317
+    "‘Is that the way YOU manage?’ Alice asked.",
1318
+    "The Hatter shook his head mournfully. ‘Not I!’ he replied. ‘We",
1319
+    "quarrelled last March--just before HE went mad, you know--’ (pointing",
1320
+    "with his tea spoon at the March Hare,) ‘--it was at the great concert",
1321
+    "given by the Queen of Hearts, and I had to sing",
1322
+    "     “Twinkle, twinkle, little bat!",
1323
+    "     How I wonder what you’re at!”",
1324
+    "You know the song, perhaps?’",
1325
+    "‘I’ve heard something like it,’ said Alice.",
1326
+    "‘It goes on, you know,’ the Hatter continued, ‘in this way:--",
1327
+    "     “Up above the world you fly,",
1328
+    "     Like a tea-tray in the sky.",
1329
+    "         Twinkle, twinkle--“’",
1330
+    "Here the Dormouse shook itself, and began singing in its sleep ‘Twinkle,",
1331
+    "twinkle, twinkle, twinkle--’ and went on so long that they had to pinch",
1332
+    "it to make it stop.",
1333
+    "‘Well, I’d hardly finished the first verse,’ said the Hatter, ‘when the",
1334
+    "Queen jumped up and bawled out, “He’s murdering the time! Off with his",
1335
+    "head!”’",
1336
+    "‘How dreadfully savage!’ exclaimed Alice.",
1337
+    "‘And ever since that,’ the Hatter went on in a mournful tone, ‘he won’t",
1338
+    "do a thing I ask! It’s always six o’clock now.’",
1339
+    "A bright idea came into Alice’s head. ‘Is that the reason so many",
1340
+    "tea-things are put out here?’ she asked.",
1341
+    "‘Yes, that’s it,’ said the Hatter with a sigh: ‘it’s always tea-time,",
1342
+    "and we’ve no time to wash the things between whiles.’",
1343
+    "‘Then you keep moving round, I suppose?’ said Alice.",
1344
+    "‘Exactly so,’ said the Hatter: ‘as the things get used up.’",
1345
+    "‘But what happens when you come to the beginning again?’ Alice ventured",
1346
+    "to ask.",
1347
+    "‘Suppose we change the subject,’ the March Hare interrupted, yawning.",
1348
+    "‘I’m getting tired of this. I vote the young lady tells us a story.’",
1349
+    "‘I’m afraid I don’t know one,’ said Alice, rather alarmed at the",
1350
+    "proposal.",
1351
+    "‘Then the Dormouse shall!’ they both cried. ‘Wake up, Dormouse!’ And",
1352
+    "they pinched it on both sides at once.",
1353
+    "The Dormouse slowly opened his eyes. ‘I wasn’t asleep,’ he said in a",
1354
+    "hoarse, feeble voice: ‘I heard every word you fellows were saying.’",
1355
+    "‘Tell us a story!’ said the March Hare.",
1356
+    "‘Yes, please do!’ pleaded Alice.",
1357
+    "‘And be quick about it,’ added the Hatter, ‘or you’ll be asleep again",
1358
+    "before it’s done.’",
1359
+    "‘Once upon a time there were three little sisters,’ the Dormouse began",
1360
+    "in a great hurry; ‘and their names were Elsie, Lacie, and Tillie; and",
1361
+    "they lived at the bottom of a well--’",
1362
+    "‘What did they live on?’ said Alice, who always took a great interest in",
1363
+    "questions of eating and drinking.",
1364
+    "‘They lived on treacle,’ said the Dormouse, after thinking a minute or",
1365
+    "two.",
1366
+    "‘They couldn’t have done that, you know,’ Alice gently remarked; ‘they’d",
1367
+    "have been ill.’",
1368
+    "‘So they were,’ said the Dormouse; ‘VERY ill.’",
1369
+    "Alice tried to fancy to herself what such an extraordinary ways of",
1370
+    "living would be like, but it puzzled her too much, so she went on: ‘But",
1371
+    "why did they live at the bottom of a well?’",
1372
+    "‘Take some more tea,’ the March Hare said to Alice, very earnestly.",
1373
+    "‘I’ve had nothing yet,’ Alice replied in an offended tone, ‘so I can’t",
1374
+    "take more.’",
1375
+    "‘You mean you can’t take LESS,’ said the Hatter: ‘it’s very easy to take",
1376
+    "MORE than nothing.’",
1377
+    "‘Nobody asked YOUR opinion,’ said Alice.",
1378
+    "‘Who’s making personal remarks now?’ the Hatter asked triumphantly.",
1379
+    "Alice did not quite know what to say to this: so she helped herself",
1380
+    "to some tea and bread-and-butter, and then turned to the Dormouse, and",
1381
+    "repeated her question. ‘Why did they live at the bottom of a well?’",
1382
+    "The Dormouse again took a minute or two to think about it, and then",
1383
+    "said, ‘It was a treacle-well.’",
1384
+    "‘There’s no such thing!’ Alice was beginning very angrily, but the",
1385
+    "Hatter and the March Hare went ‘Sh! sh!’ and the Dormouse sulkily",
1386
+    "remarked, ‘If you can’t be civil, you’d better finish the story for",
1387
+    "yourself.’",
1388
+    "‘No, please go on!’ Alice said very humbly; ‘I won’t interrupt again. I",
1389
+    "dare say there may be ONE.’",
1390
+    "‘One, indeed!’ said the Dormouse indignantly. However, he consented to",
1391
+    "go on. ‘And so these three little sisters--they were learning to draw,",
1392
+    "you know--’",
1393
+    "‘What did they draw?’ said Alice, quite forgetting her promise.",
1394
+    "‘Treacle,’ said the Dormouse, without considering at all this time.",
1395
+    "‘I want a clean cup,’ interrupted the Hatter: ‘let’s all move one place",
1396
+    "on.’",
1397
+    "He moved on as he spoke, and the Dormouse followed him: the March Hare",
1398
+    "moved into the Dormouse’s place, and Alice rather unwillingly took",
1399
+    "the place of the March Hare. The Hatter was the only one who got any",
1400
+    "advantage from the change: and Alice was a good deal worse off than",
1401
+    "before, as the March Hare had just upset the milk-jug into his plate.",
1402
+    "Alice did not wish to offend the Dormouse again, so she began very",
1403
+    "cautiously: ‘But I don’t understand. Where did they draw the treacle",
1404
+    "from?’",
1405
+    "‘You can draw water out of a water-well,’ said the Hatter; ‘so I should",
1406
+    "think you could draw treacle out of a treacle-well--eh, stupid?’",
1407
+    "‘But they were IN the well,’ Alice said to the Dormouse, not choosing to",
1408
+    "notice this last remark.",
1409
+    "‘Of course they were’, said the Dormouse; ‘--well in.’",
1410
+    "This answer so confused poor Alice, that she let the Dormouse go on for",
1411
+    "some time without interrupting it.",
1412
+    "‘They were learning to draw,’ the Dormouse went on, yawning and rubbing",
1413
+    "its eyes, for it was getting very sleepy; ‘and they drew all manner of",
1414
+    "things--everything that begins with an M--’",
1415
+    "‘Why with an M?’ said Alice.",
1416
+    "‘Why not?’ said the March Hare.",
1417
+    "Alice was silent.",
1418
+    "The Dormouse had closed its eyes by this time, and was going off into",
1419
+    "a doze; but, on being pinched by the Hatter, it woke up again with",
1420
+    "a little shriek, and went on: ‘--that begins with an M, such as",
1421
+    "mouse-traps, and the moon, and memory, and muchness--you know you say",
1422
+    "things are “much of a muchness”--did you ever see such a thing as a",
1423
+    "drawing of a muchness?’",
1424
+    "‘Really, now you ask me,’ said Alice, very much confused, ‘I don’t",
1425
+    "think--’",
1426
+    "‘Then you shouldn’t talk,’ said the Hatter.",
1427
+    "This piece of rudeness was more than Alice could bear: she got up in",
1428
+    "great disgust, and walked off; the Dormouse fell asleep instantly, and",
1429
+    "neither of the others took the least notice of her going, though she",
1430
+    "looked back once or twice, half hoping that they would call after her:",
1431
+    "the last time she saw them, they were trying to put the Dormouse into",
1432
+    "the teapot.",
1433
+    "‘At any rate I’ll never go THERE again!’ said Alice as she picked her",
1434
+    "way through the wood. ‘It’s the stupidest tea-party I ever was at in all",
1435
+    "my life!’",
1436
+    "Just as she said this, she noticed that one of the trees had a door",
1437
+    "leading right into it. ‘That’s very curious!’ she thought. ‘But",
1438
+    "everything’s curious today. I think I may as well go in at once.’ And in",
1439
+    "she went.",
1440
+    "Once more she found herself in the long hall, and close to the little",
1441
+    "glass table. ‘Now, I’ll manage better this time,’ she said to herself,",
1442
+    "and began by taking the little golden key, and unlocking the door that",
1443
+    "led into the garden. Then she went to work nibbling at the mushroom (she",
1444
+    "had kept a piece of it in her pocket) till she was about a foot high:",
1445
+    "then she walked down the little passage: and THEN--she found herself at",
1446
+    "last in the beautiful garden, among the bright flower-beds and the cool",
1447
+    "fountains.",
1448
+    "CHAPTER VIII. The Queen’s Croquet-Ground",
1449
+    "A large rose-tree stood near the entrance of the garden: the roses",
1450
+    "growing on it were white, but there were three gardeners at it, busily",
1451
+    "painting them red. Alice thought this a very curious thing, and she went",
1452
+    "nearer to watch them, and just as she came up to them she heard one of",
1453
+    "them say, ‘Look out now, Five! Don’t go splashing paint over me like",
1454
+    "that!’",
1455
+    "‘I couldn’t help it,’ said Five, in a sulky tone; ‘Seven jogged my",
1456
+    "elbow.’",
1457
+    "On which Seven looked up and said, ‘That’s right, Five! Always lay the",
1458
+    "blame on others!’",
1459
+    "‘YOU’D better not talk!’ said Five. ‘I heard the Queen say only",
1460
+    "yesterday you deserved to be beheaded!’",
1461
+    "‘What for?’ said the one who had spoken first.",
1462
+    "‘That’s none of YOUR business, Two!’ said Seven.",
1463
+    "‘Yes, it IS his business!’ said Five, ‘and I’ll tell him--it was for",
1464
+    "bringing the cook tulip-roots instead of onions.’",
1465
+    "Seven flung down his brush, and had just begun ‘Well, of all the unjust",
1466
+    "things--’ when his eye chanced to fall upon Alice, as she stood watching",
1467
+    "them, and he checked himself suddenly: the others looked round also, and",
1468
+    "all of them bowed low.",
1469
+    "‘Would you tell me,’ said Alice, a little timidly, ‘why you are painting",
1470
+    "those roses?’",
1471
+    "Five and Seven said nothing, but looked at Two. Two began in a low",
1472
+    "voice, ‘Why the fact is, you see, Miss, this here ought to have been a",
1473
+    "RED rose-tree, and we put a white one in by mistake; and if the Queen",
1474
+    "was to find it out, we should all have our heads cut off, you know.",
1475
+    "So you see, Miss, we’re doing our best, afore she comes, to--’ At this",
1476
+    "moment Five, who had been anxiously looking across the garden, called",
1477
+    "out ‘The Queen! The Queen!’ and the three gardeners instantly threw",
1478
+    "themselves flat upon their faces. There was a sound of many footsteps,",
1479
+    "and Alice looked round, eager to see the Queen.",
1480
+    "First came ten soldiers carrying clubs; these were all shaped like",
1481
+    "the three gardeners, oblong and flat, with their hands and feet at the",
1482
+    "corners: next the ten courtiers; these were ornamented all over with",
1483
+    "diamonds, and walked two and two, as the soldiers did. After these came",
1484
+    "the royal children; there were ten of them, and the little dears came",
1485
+    "jumping merrily along hand in hand, in couples: they were all ornamented",
1486
+    "with hearts. Next came the guests, mostly Kings and Queens, and among",
1487
+    "them Alice recognised the White Rabbit: it was talking in a hurried",
1488
+    "nervous manner, smiling at everything that was said, and went by without",
1489
+    "noticing her. Then followed the Knave of Hearts, carrying the King’s",
1490
+    "crown on a crimson velvet cushion; and, last of all this grand",
1491
+    "procession, came THE KING AND QUEEN OF HEARTS.",
1492
+    "Alice was rather doubtful whether she ought not to lie down on her face",
1493
+    "like the three gardeners, but she could not remember ever having heard",
1494
+    "of such a rule at processions; ‘and besides, what would be the use of",
1495
+    "a procession,’ thought she, ‘if people had all to lie down upon their",
1496
+    "faces, so that they couldn’t see it?’ So she stood still where she was,",
1497
+    "and waited.",
1498
+    "When the procession came opposite to Alice, they all stopped and looked",
1499
+    "at her, and the Queen said severely ‘Who is this?’ She said it to the",
1500
+    "Knave of Hearts, who only bowed and smiled in reply.",
1501
+    "‘Idiot!’ said the Queen, tossing her head impatiently; and, turning to",
1502
+    "Alice, she went on, ‘What’s your name, child?’",
1503
+    "‘My name is Alice, so please your Majesty,’ said Alice very politely;",
1504
+    "but she added, to herself, ‘Why, they’re only a pack of cards, after",
1505
+    "all. I needn’t be afraid of them!’",
1506
+    "‘And who are THESE?’ said the Queen, pointing to the three gardeners who",
1507
+    "were lying round the rosetree; for, you see, as they were lying on their",
1508
+    "faces, and the pattern on their backs was the same as the rest of the",
1509
+    "pack, she could not tell whether they were gardeners, or soldiers, or",
1510
+    "courtiers, or three of her own children.",
1511
+    "‘How should I know?’ said Alice, surprised at her own courage. ‘It’s no",
1512
+    "business of MINE.’",
1513
+    "The Queen turned crimson with fury, and, after glaring at her for a",
1514
+    "moment like a wild beast, screamed ‘Off with her head! Off--’",
1515
+    "‘Nonsense!’ said Alice, very loudly and decidedly, and the Queen was",
1516
+    "silent.",
1517
+    "The King laid his hand upon her arm, and timidly said ‘Consider, my",
1518
+    "dear: she is only a child!’",
1519
+    "The Queen turned angrily away from him, and said to the Knave ‘Turn them",
1520
+    "over!’",
1521
+    "The Knave did so, very carefully, with one foot.",
1522
+    "‘Get up!’ said the Queen, in a shrill, loud voice, and the three",
1523
+    "gardeners instantly jumped up, and began bowing to the King, the Queen,",
1524
+    "the royal children, and everybody else.",
1525
+    "‘Leave off that!’ screamed the Queen. ‘You make me giddy.’ And then,",
1526
+    "turning to the rose-tree, she went on, ‘What HAVE you been doing here?’",
1527
+    "‘May it please your Majesty,’ said Two, in a very humble tone, going",
1528
+    "down on one knee as he spoke, ‘we were trying--’",
1529
+    "‘I see!’ said the Queen, who had meanwhile been examining the roses.",
1530
+    "‘Off with their heads!’ and the procession moved on, three of the",
1531
+    "soldiers remaining behind to execute the unfortunate gardeners, who ran",
1532
+    "to Alice for protection.",
1533
+    "‘You shan’t be beheaded!’ said Alice, and she put them into a large",
1534
+    "flower-pot that stood near. The three soldiers wandered about for a",
1535
+    "minute or two, looking for them, and then quietly marched off after the",
1536
+    "others.",
1537
+    "‘Are their heads off?’ shouted the Queen.",
1538
+    "‘Their heads are gone, if it please your Majesty!’ the soldiers shouted",
1539
+    "in reply.",
1540
+    "‘That’s right!’ shouted the Queen. ‘Can you play croquet?’",
1541
+    "The soldiers were silent, and looked at Alice, as the question was",
1542
+    "evidently meant for her.",
1543
+    "‘Yes!’ shouted Alice.",
1544
+    "‘Come on, then!’ roared the Queen, and Alice joined the procession,",
1545
+    "wondering very much what would happen next.",
1546
+    "‘It’s--it’s a very fine day!’ said a timid voice at her side. She was",
1547
+    "walking by the White Rabbit, who was peeping anxiously into her face.",
1548
+    "‘Very,’ said Alice: ‘--where’s the Duchess?’",
1549
+    "‘Hush! Hush!’ said the Rabbit in a low, hurried tone. He looked",
1550
+    "anxiously over his shoulder as he spoke, and then raised himself upon",
1551
+    "tiptoe, put his mouth close to her ear, and whispered ‘She’s under",
1552
+    "sentence of execution.’",
1553
+    "‘What for?’ said Alice.",
1554
+    "‘Did you say “What a pity!”?’ the Rabbit asked.",
1555
+    "‘No, I didn’t,’ said Alice: ‘I don’t think it’s at all a pity. I said",
1556
+    "“What for?”’",
1557
+    "‘She boxed the Queen’s ears--’ the Rabbit began. Alice gave a little",
1558
+    "scream of laughter. ‘Oh, hush!’ the Rabbit whispered in a frightened",
1559
+    "tone. ‘The Queen will hear you! You see, she came rather late, and the",
1560
+    "Queen said--’",
1561
+    "‘Get to your places!’ shouted the Queen in a voice of thunder, and",
1562
+    "people began running about in all directions, tumbling up against each",
1563
+    "other; however, they got settled down in a minute or two, and the game",
1564
+    "began. Alice thought she had never seen such a curious croquet-ground in",
1565
+    "her life; it was all ridges and furrows; the balls were live hedgehogs,",
1566
+    "the mallets live flamingoes, and the soldiers had to double themselves",
1567
+    "up and to stand on their hands and feet, to make the arches.",
1568
+    "The chief difficulty Alice found at first was in managing her flamingo:",
1569
+    "she succeeded in getting its body tucked away, comfortably enough, under",
1570
+    "her arm, with its legs hanging down, but generally, just as she had got",
1571
+    "its neck nicely straightened out, and was going to give the hedgehog a",
1572
+    "blow with its head, it WOULD twist itself round and look up in her face,",
1573
+    "with such a puzzled expression that she could not help bursting out",
1574
+    "laughing: and when she had got its head down, and was going to begin",
1575
+    "again, it was very provoking to find that the hedgehog had unrolled",
1576
+    "itself, and was in the act of crawling away: besides all this, there was",
1577
+    "generally a ridge or furrow in the way wherever she wanted to send the",
1578
+    "hedgehog to, and, as the doubled-up soldiers were always getting up",
1579
+    "and walking off to other parts of the ground, Alice soon came to the",
1580
+    "conclusion that it was a very difficult game indeed.",
1581
+    "The players all played at once without waiting for turns, quarrelling",
1582
+    "all the while, and fighting for the hedgehogs; and in a very short",
1583
+    "time the Queen was in a furious passion, and went stamping about, and",
1584
+    "shouting ‘Off with his head!’ or ‘Off with her head!’ about once in a",
1585
+    "minute.",
1586
+    "Alice began to feel very uneasy: to be sure, she had not as yet had any",
1587
+    "dispute with the Queen, but she knew that it might happen any minute,",
1588
+    "‘and then,’ thought she, ‘what would become of me? They’re dreadfully",
1589
+    "fond of beheading people here; the great wonder is, that there’s any one",
1590
+    "left alive!’",
1591
+    "She was looking about for some way of escape, and wondering whether she",
1592
+    "could get away without being seen, when she noticed a curious appearance",
1593
+    "in the air: it puzzled her very much at first, but, after watching it",
1594
+    "a minute or two, she made it out to be a grin, and she said to herself",
1595
+    "‘It’s the Cheshire Cat: now I shall have somebody to talk to.’",
1596
+    "‘How are you getting on?’ said the Cat, as soon as there was mouth",
1597
+    "enough for it to speak with.",
1598
+    "Alice waited till the eyes appeared, and then nodded. ‘It’s no use",
1599
+    "speaking to it,’ she thought, ‘till its ears have come, or at least one",
1600
+    "of them.’ In another minute the whole head appeared, and then Alice put",
1601
+    "down her flamingo, and began an account of the game, feeling very glad",
1602
+    "she had someone to listen to her. The Cat seemed to think that there was",
1603
+    "enough of it now in sight, and no more of it appeared.",
1604
+    "‘I don’t think they play at all fairly,’ Alice began, in rather a",
1605
+    "complaining tone, ‘and they all quarrel so dreadfully one can’t hear",
1606
+    "oneself speak--and they don’t seem to have any rules in particular;",
1607
+    "at least, if there are, nobody attends to them--and you’ve no idea how",
1608
+    "confusing it is all the things being alive; for instance, there’s the",
1609
+    "arch I’ve got to go through next walking about at the other end of the",
1610
+    "ground--and I should have croqueted the Queen’s hedgehog just now, only",
1611
+    "it ran away when it saw mine coming!’",
1612
+    "‘How do you like the Queen?’ said the Cat in a low voice.",
1613
+    "‘Not at all,’ said Alice: ‘she’s so extremely--’ Just then she noticed",
1614
+    "that the Queen was close behind her, listening: so she went on,",
1615
+    "‘--likely to win, that it’s hardly worth while finishing the game.’",
1616
+    "The Queen smiled and passed on.",
1617
+    "‘Who ARE you talking to?’ said the King, going up to Alice, and looking",
1618
+    "at the Cat’s head with great curiosity.",
1619
+    "‘It’s a friend of mine--a Cheshire Cat,’ said Alice: ‘allow me to",
1620
+    "introduce it.’",
1621
+    "‘I don’t like the look of it at all,’ said the King: ‘however, it may",
1622
+    "kiss my hand if it likes.’",
1623
+    "‘I’d rather not,’ the Cat remarked.",
1624
+    "‘Don’t be impertinent,’ said the King, ‘and don’t look at me like that!’",
1625
+    "He got behind Alice as he spoke.",
1626
+    "‘A cat may look at a king,’ said Alice. ‘I’ve read that in some book,",
1627
+    "but I don’t remember where.’",
1628
+    "‘Well, it must be removed,’ said the King very decidedly, and he called",
1629
+    "the Queen, who was passing at the moment, ‘My dear! I wish you would",
1630
+    "have this cat removed!’",
1631
+    "The Queen had only one way of settling all difficulties, great or small.",
1632
+    "‘Off with his head!’ she said, without even looking round.",
1633
+    "‘I’ll fetch the executioner myself,’ said the King eagerly, and he",
1634
+    "hurried off.",
1635
+    "Alice thought she might as well go back, and see how the game was going",
1636
+    "on, as she heard the Queen’s voice in the distance, screaming with",
1637
+    "passion. She had already heard her sentence three of the players to be",
1638
+    "executed for having missed their turns, and she did not like the look",
1639
+    "of things at all, as the game was in such confusion that she never knew",
1640
+    "whether it was her turn or not. So she went in search of her hedgehog.",
1641
+    "The hedgehog was engaged in a fight with another hedgehog, which seemed",
1642
+    "to Alice an excellent opportunity for croqueting one of them with the",
1643
+    "other: the only difficulty was, that her flamingo was gone across to the",
1644
+    "other side of the garden, where Alice could see it trying in a helpless",
1645
+    "sort of way to fly up into a tree.",
1646
+    "By the time she had caught the flamingo and brought it back, the fight",
1647
+    "was over, and both the hedgehogs were out of sight: ‘but it doesn’t",
1648
+    "matter much,’ thought Alice, ‘as all the arches are gone from this side",
1649
+    "of the ground.’ So she tucked it away under her arm, that it might not",
1650
+    "escape again, and went back for a little more conversation with her",
1651
+    "friend.",
1652
+    "When she got back to the Cheshire Cat, she was surprised to find quite a",
1653
+    "large crowd collected round it: there was a dispute going on between",
1654
+    "the executioner, the King, and the Queen, who were all talking at once,",
1655
+    "while all the rest were quite silent, and looked very uncomfortable.",
1656
+    "The moment Alice appeared, she was appealed to by all three to settle",
1657
+    "the question, and they repeated their arguments to her, though, as they",
1658
+    "all spoke at once, she found it very hard indeed to make out exactly",
1659
+    "what they said.",
1660
+    "The executioner’s argument was, that you couldn’t cut off a head unless",
1661
+    "there was a body to cut it off from: that he had never had to do such a",
1662
+    "thing before, and he wasn’t going to begin at HIS time of life.",
1663
+    "The King’s argument was, that anything that had a head could be",
1664
+    "beheaded, and that you weren’t to talk nonsense.",
1665
+    "The Queen’s argument was, that if something wasn’t done about it in less",
1666
+    "than no time she’d have everybody executed, all round. (It was this last",
1667
+    "remark that had made the whole party look so grave and anxious.)",
1668
+    "Alice could think of nothing else to say but ‘It belongs to the Duchess:",
1669
+    "you’d better ask HER about it.’",
1670
+    "‘She’s in prison,’ the Queen said to the executioner: ‘fetch her here.’",
1671
+    "And the executioner went off like an arrow.",
1672
+    " The Cat’s head began fading away the moment he was gone, and,",
1673
+    "by the time he had come back with the Duchess, it had entirely",
1674
+    "disappeared; so the King and the executioner ran wildly up and down",
1675
+    "looking for it, while the rest of the party went back to the game.",
1676
+    "CHAPTER IX. The Mock Turtle’s Story",
1677
+    "‘You can’t think how glad I am to see you again, you dear old thing!’",
1678
+    "said the Duchess, as she tucked her arm affectionately into Alice’s, and",
1679
+    "they walked off together.",
1680
+    "Alice was very glad to find her in such a pleasant temper, and thought",
1681
+    "to herself that perhaps it was only the pepper that had made her so",
1682
+    "savage when they met in the kitchen.",
1683
+    "‘When I’M a Duchess,’ she said to herself, (not in a very hopeful tone",
1684
+    "though), ‘I won’t have any pepper in my kitchen AT ALL. Soup does very",
1685
+    "well without--Maybe it’s always pepper that makes people hot-tempered,’",
1686
+    "she went on, very much pleased at having found out a new kind of",
1687
+    "rule, ‘and vinegar that makes them sour--and camomile that makes",
1688
+    "them bitter--and--and barley-sugar and such things that make children",
1689
+    "sweet-tempered. I only wish people knew that: then they wouldn’t be so",
1690
+    "stingy about it, you know--’",
1691
+    "She had quite forgotten the Duchess by this time, and was a little",
1692
+    "startled when she heard her voice close to her ear. ‘You’re thinking",
1693
+    "about something, my dear, and that makes you forget to talk. I can’t",
1694
+    "tell you just now what the moral of that is, but I shall remember it in",
1695
+    "a bit.’",
1696
+    "‘Perhaps it hasn’t one,’ Alice ventured to remark.",
1697
+    "‘Tut, tut, child!’ said the Duchess. ‘Everything’s got a moral, if only",
1698
+    "you can find it.’ And she squeezed herself up closer to Alice’s side as",
1699
+    "she spoke.",
1700
+    "Alice did not much like keeping so close to her: first, because the",
1701
+    "Duchess was VERY ugly; and secondly, because she was exactly the",
1702
+    "right height to rest her chin upon Alice’s shoulder, and it was an",
1703
+    "uncomfortably sharp chin. However, she did not like to be rude, so she",
1704
+    "bore it as well as she could.",
1705
+    "‘The game’s going on rather better now,’ she said, by way of keeping up",
1706
+    "the conversation a little.",
1707
+    "‘’Tis so,’ said the Duchess: ‘and the moral of that is--“Oh, ‘tis love,",
1708
+    "‘tis love, that makes the world go round!”’",
1709
+    "‘Somebody said,’ Alice whispered, ‘that it’s done by everybody minding",
1710
+    "their own business!’",
1711
+    "‘Ah, well! It means much the same thing,’ said the Duchess, digging her",
1712
+    "sharp little chin into Alice’s shoulder as she added, ‘and the moral",
1713
+    "of THAT is--“Take care of the sense, and the sounds will take care of",
1714
+    "themselves.”’",
1715
+    "‘How fond she is of finding morals in things!’ Alice thought to herself.",
1716
+    "‘I dare say you’re wondering why I don’t put my arm round your waist,’",
1717
+    "the Duchess said after a pause: ‘the reason is, that I’m doubtful about",
1718
+    "the temper of your flamingo. Shall I try the experiment?’",
1719
+    "‘HE might bite,’ Alice cautiously replied, not feeling at all anxious to",
1720
+    "have the experiment tried.",
1721
+    "‘Very true,’ said the Duchess: ‘flamingoes and mustard both bite. And",
1722
+    "the moral of that is--“Birds of a feather flock together.”’",
1723
+    "‘Only mustard isn’t a bird,’ Alice remarked.",
1724
+    "‘Right, as usual,’ said the Duchess: ‘what a clear way you have of",
1725
+    "putting things!’",
1726
+    "‘It’s a mineral, I THINK,’ said Alice.",
1727
+    "‘Of course it is,’ said the Duchess, who seemed ready to agree to",
1728
+    "everything that Alice said; ‘there’s a large mustard-mine near here. And",
1729
+    "the moral of that is--“The more there is of mine, the less there is of",
1730
+    "yours.”’",
1731
+    "‘Oh, I know!’ exclaimed Alice, who had not attended to this last remark,",
1732
+    "‘it’s a vegetable. It doesn’t look like one, but it is.’",
1733
+    "‘I quite agree with you,’ said the Duchess; ‘and the moral of that",
1734
+    "is--“Be what you would seem to be”--or if you’d like it put more",
1735
+    "simply--“Never imagine yourself not to be otherwise than what it might",
1736
+    "appear to others that what you were or might have been was not otherwise",
1737
+    "than what you had been would have appeared to them to be otherwise.”’",
1738
+    "‘I think I should understand that better,’ Alice said very politely, ‘if",
1739
+    "I had it written down: but I can’t quite follow it as you say it.’",
1740
+    "‘That’s nothing to what I could say if I chose,’ the Duchess replied, in",
1741
+    "a pleased tone.",
1742
+    "‘Pray don’t trouble yourself to say it any longer than that,’ said",
1743
+    "Alice.",
1744
+    "‘Oh, don’t talk about trouble!’ said the Duchess. ‘I make you a present",
1745
+    "of everything I’ve said as yet.’",
1746
+    "‘A cheap sort of present!’ thought Alice. ‘I’m glad they don’t give",
1747
+    "birthday presents like that!’ But she did not venture to say it out",
1748
+    "loud.",
1749
+    "‘Thinking again?’ the Duchess asked, with another dig of her sharp",
1750
+    "little chin.",
1751
+    "‘I’ve a right to think,’ said Alice sharply, for she was beginning to",
1752
+    "feel a little worried.",
1753
+    "‘Just about as much right,’ said the Duchess, ‘as pigs have to fly; and",
1754
+    "the m--’",
1755
+    "But here, to Alice’s great surprise, the Duchess’s voice died away, even",
1756
+    "in the middle of her favourite word ‘moral,’ and the arm that was linked",
1757
+    "into hers began to tremble. Alice looked up, and there stood the Queen",
1758
+    "in front of them, with her arms folded, frowning like a thunderstorm.",
1759
+    "‘A fine day, your Majesty!’ the Duchess began in a low, weak voice.",
1760
+    "‘Now, I give you fair warning,’ shouted the Queen, stamping on the",
1761
+    "ground as she spoke; ‘either you or your head must be off, and that in",
1762
+    "about half no time! Take your choice!’",
1763
+    "The Duchess took her choice, and was gone in a moment.",
1764
+    "‘Let’s go on with the game,’ the Queen said to Alice; and Alice was",
1765
+    "too much frightened to say a word, but slowly followed her back to the",
1766
+    "croquet-ground.",
1767
+    "The other guests had taken advantage of the Queen’s absence, and were",
1768
+    "resting in the shade: however, the moment they saw her, they hurried",
1769
+    "back to the game, the Queen merely remarking that a moment’s delay would",
1770
+    "cost them their lives.",
1771
+    "All the time they were playing the Queen never left off quarrelling with",
1772
+    "the other players, and shouting ‘Off with his head!’ or ‘Off with her",
1773
+    "head!’ Those whom she sentenced were taken into custody by the soldiers,",
1774
+    "who of course had to leave off being arches to do this, so that by",
1775
+    "the end of half an hour or so there were no arches left, and all the",
1776
+    "players, except the King, the Queen, and Alice, were in custody and",
1777
+    "under sentence of execution.",
1778
+    "Then the Queen left off, quite out of breath, and said to Alice, ‘Have",
1779
+    "you seen the Mock Turtle yet?’",
1780
+    "‘No,’ said Alice. ‘I don’t even know what a Mock Turtle is.’",
1781
+    "‘It’s the thing Mock Turtle Soup is made from,’ said the Queen.",
1782
+    "‘I never saw one, or heard of one,’ said Alice.",
1783
+    "‘Come on, then,’ said the Queen, ‘and he shall tell you his history,’",
1784
+    "As they walked off together, Alice heard the King say in a low voice,",
1785
+    "to the company generally, ‘You are all pardoned.’ ‘Come, THAT’S a good",
1786
+    "thing!’ she said to herself, for she had felt quite unhappy at the",
1787
+    "number of executions the Queen had ordered.",
1788
+    "They very soon came upon a Gryphon, lying fast asleep in the sun.",
1789
+    "(IF you don’t know what a Gryphon is, look at the picture.) ‘Up, lazy",
1790
+    "thing!’ said the Queen, ‘and take this young lady to see the Mock",
1791
+    "Turtle, and to hear his history. I must go back and see after some",
1792
+    "executions I have ordered’; and she walked off, leaving Alice alone with",
1793
+    "the Gryphon. Alice did not quite like the look of the creature, but on",
1794
+    "the whole she thought it would be quite as safe to stay with it as to go",
1795
+    "after that savage Queen: so she waited.",
1796
+    "The Gryphon sat up and rubbed its eyes: then it watched the Queen till",
1797
+    "she was out of sight: then it chuckled. ‘What fun!’ said the Gryphon,",
1798
+    "half to itself, half to Alice.",
1799
+    "‘What IS the fun?’ said Alice.",
1800
+    "‘Why, SHE,’ said the Gryphon. ‘It’s all her fancy, that: they never",
1801
+    "executes nobody, you know. Come on!’",
1802
+    "‘Everybody says “come on!” here,’ thought Alice, as she went slowly",
1803
+    "after it: ‘I never was so ordered about in all my life, never!’",
1804
+    "They had not gone far before they saw the Mock Turtle in the distance,",
1805
+    "sitting sad and lonely on a little ledge of rock, and, as they came",
1806
+    "nearer, Alice could hear him sighing as if his heart would break. She",
1807
+    "pitied him deeply. ‘What is his sorrow?’ she asked the Gryphon, and the",
1808
+    "Gryphon answered, very nearly in the same words as before, ‘It’s all his",
1809
+    "fancy, that: he hasn’t got no sorrow, you know. Come on!’",
1810
+    "So they went up to the Mock Turtle, who looked at them with large eyes",
1811
+    "full of tears, but said nothing.",
1812
+    "‘This here young lady,’ said the Gryphon, ‘she wants for to know your",
1813
+    "history, she do.’",
1814
+    "‘I’ll tell it her,’ said the Mock Turtle in a deep, hollow tone: ‘sit",
1815
+    "down, both of you, and don’t speak a word till I’ve finished.’",
1816
+    "So they sat down, and nobody spoke for some minutes. Alice thought to",
1817
+    "herself, ‘I don’t see how he can EVEN finish, if he doesn’t begin.’ But",
1818
+    "she waited patiently.",
1819
+    "‘Once,’ said the Mock Turtle at last, with a deep sigh, ‘I was a real",
1820
+    "Turtle.’",
1821
+    "These words were followed by a very long silence, broken only by an",
1822
+    "occasional exclamation of ‘Hjckrrh!’ from the Gryphon, and the constant",
1823
+    "heavy sobbing of the Mock Turtle. Alice was very nearly getting up and",
1824
+    "saying, ‘Thank you, sir, for your interesting story,’ but she could",
1825
+    "not help thinking there MUST be more to come, so she sat still and said",
1826
+    "nothing.",
1827
+    "‘When we were little,’ the Mock Turtle went on at last, more calmly,",
1828
+    "though still sobbing a little now and then, ‘we went to school in the",
1829
+    "sea. The master was an old Turtle--we used to call him Tortoise--’",
1830
+    "‘Why did you call him Tortoise, if he wasn’t one?’ Alice asked.",
1831
+    "‘We called him Tortoise because he taught us,’ said the Mock Turtle",
1832
+    "angrily: ‘really you are very dull!’",
1833
+    "‘You ought to be ashamed of yourself for asking such a simple question,’",
1834
+    "added the Gryphon; and then they both sat silent and looked at poor",
1835
+    "Alice, who felt ready to sink into the earth. At last the Gryphon said",
1836
+    "to the Mock Turtle, ‘Drive on, old fellow! Don’t be all day about it!’",
1837
+    "and he went on in these words:",
1838
+    "‘Yes, we went to school in the sea, though you mayn’t believe it--’",
1839
+    "‘I never said I didn’t!’ interrupted Alice.",
1840
+    "‘You did,’ said the Mock Turtle.",
1841
+    "‘Hold your tongue!’ added the Gryphon, before Alice could speak again.",
1842
+    "The Mock Turtle went on.",
1843
+    "‘We had the best of educations--in fact, we went to school every day--’",
1844
+    "‘I’VE been to a day-school, too,’ said Alice; ‘you needn’t be so proud",
1845
+    "as all that.’",
1846
+    "‘With extras?’ asked the Mock Turtle a little anxiously.",
1847
+    "‘Yes,’ said Alice, ‘we learned French and music.’",
1848
+    "‘And washing?’ said the Mock Turtle.",
1849
+    "‘Certainly not!’ said Alice indignantly.",
1850
+    "‘Ah! then yours wasn’t a really good school,’ said the Mock Turtle in",
1851
+    "a tone of great relief. ‘Now at OURS they had at the end of the bill,",
1852
+    "“French, music, AND WASHING--extra.”’",
1853
+    "‘You couldn’t have wanted it much,’ said Alice; ‘living at the bottom of",
1854
+    "the sea.’",
1855
+    "‘I couldn’t afford to learn it.’ said the Mock Turtle with a sigh. ‘I",
1856
+    "only took the regular course.’",
1857
+    "‘What was that?’ inquired Alice.",
1858
+    "‘Reeling and Writhing, of course, to begin with,’ the Mock Turtle",
1859
+    "replied; ‘and then the different branches of Arithmetic--Ambition,",
1860
+    "Distraction, Uglification, and Derision.’",
1861
+    "‘I never heard of “Uglification,”’ Alice ventured to say. ‘What is it?’",
1862
+    "The Gryphon lifted up both its paws in surprise. ‘What! Never heard of",
1863
+    "uglifying!’ it exclaimed. ‘You know what to beautify is, I suppose?’",
1864
+    "‘Yes,’ said Alice doubtfully: ‘it means--to--make--anything--prettier.’",
1865
+    "‘Well, then,’ the Gryphon went on, ‘if you don’t know what to uglify is,",
1866
+    "you ARE a simpleton.’",
1867
+    "Alice did not feel encouraged to ask any more questions about it, so she",
1868
+    "turned to the Mock Turtle, and said ‘What else had you to learn?’",
1869
+    "‘Well, there was Mystery,’ the Mock Turtle replied, counting off",
1870
+    "the subjects on his flappers, ‘--Mystery, ancient and modern, with",
1871
+    "Seaography: then Drawling--the Drawling-master was an old conger-eel,",
1872
+    "that used to come once a week: HE taught us Drawling, Stretching, and",
1873
+    "Fainting in Coils.’",
1874
+    "‘What was THAT like?’ said Alice.",
1875
+    "‘Well, I can’t show it you myself,’ the Mock Turtle said: ‘I’m too",
1876
+    "stiff. And the Gryphon never learnt it.’",
1877
+    "‘Hadn’t time,’ said the Gryphon: ‘I went to the Classics master, though.",
1878
+    "He was an old crab, HE was.’",
1879
+    "‘I never went to him,’ the Mock Turtle said with a sigh: ‘he taught",
1880
+    "Laughing and Grief, they used to say.’",
1881
+    "‘So he did, so he did,’ said the Gryphon, sighing in his turn; and both",
1882
+    "creatures hid their faces in their paws.",
1883
+    "‘And how many hours a day did you do lessons?’ said Alice, in a hurry to",
1884
+    "change the subject.",
1885
+    "‘Ten hours the first day,’ said the Mock Turtle: ‘nine the next, and so",
1886
+    "on.’",
1887
+    "‘What a curious plan!’ exclaimed Alice.",
1888
+    "‘That’s the reason they’re called lessons,’ the Gryphon remarked:",
1889
+    "‘because they lessen from day to day.’",
1890
+    "This was quite a new idea to Alice, and she thought it over a little",
1891
+    "before she made her next remark. ‘Then the eleventh day must have been a",
1892
+    "holiday?’",
1893
+    "‘Of course it was,’ said the Mock Turtle.",
1894
+    "‘And how did you manage on the twelfth?’ Alice went on eagerly.",
1895
+    "‘That’s enough about lessons,’ the Gryphon interrupted in a very decided",
1896
+    "tone: ‘tell her something about the games now.’",
1897
+    "CHAPTER X. The Lobster Quadrille",
1898
+    "The Mock Turtle sighed deeply, and drew the back of one flapper across",
1899
+    "his eyes. He looked at Alice, and tried to speak, but for a minute or",
1900
+    "two sobs choked his voice. ‘Same as if he had a bone in his throat,’",
1901
+    "said the Gryphon: and it set to work shaking him and punching him in",
1902
+    "the back. At last the Mock Turtle recovered his voice, and, with tears",
1903
+    "running down his cheeks, he went on again:--",
1904
+    "‘You may not have lived much under the sea--’ [‘I haven’t,’ said",
1905
+    "Alice)--‘and perhaps you were never even introduced to a lobster--’",
1906
+    "(Alice began to say ‘I once tasted--’ but checked herself hastily, and",
1907
+    "said ‘No, never’) ‘--so you can have no idea what a delightful thing a",
1908
+    "Lobster Quadrille is!’",
1909
+    "‘No, indeed,’ said Alice. ‘What sort of a dance is it?’",
1910
+    "‘Why,’ said the Gryphon, ‘you first form into a line along the",
1911
+    "sea-shore--’",
1912
+    "‘Two lines!’ cried the Mock Turtle. ‘Seals, turtles, salmon, and so on;",
1913
+    "then, when you’ve cleared all the jelly-fish out of the way--’",
1914
+    "‘THAT generally takes some time,’ interrupted the Gryphon.",
1915
+    "‘--you advance twice--’",
1916
+    "‘Each with a lobster as a partner!’ cried the Gryphon.",
1917
+    "‘Of course,’ the Mock Turtle said: ‘advance twice, set to partners--’",
1918
+    "‘--change lobsters, and retire in same order,’ continued the Gryphon.",
1919
+    "‘Then, you know,’ the Mock Turtle went on, ‘you throw the--’",
1920
+    "‘The lobsters!’ shouted the Gryphon, with a bound into the air.",
1921
+    "‘--as far out to sea as you can--’",
1922
+    "‘Swim after them!’ screamed the Gryphon.",
1923
+    "‘Turn a somersault in the sea!’ cried the Mock Turtle, capering wildly",
1924
+    "about.",
1925
+    "‘Change lobsters again!’ yelled the Gryphon at the top of its voice.",
1926
+    "‘Back to land again, and that’s all the first figure,’ said the Mock",
1927
+    "Turtle, suddenly dropping his voice; and the two creatures, who had been",
1928
+    "jumping about like mad things all this time, sat down again very sadly",
1929
+    "and quietly, and looked at Alice.",
1930
+    "‘It must be a very pretty dance,’ said Alice timidly.",
1931
+    "‘Would you like to see a little of it?’ said the Mock Turtle.",
1932
+    "‘Very much indeed,’ said Alice.",
1933
+    "‘Come, let’s try the first figure!’ said the Mock Turtle to the Gryphon.",
1934
+    "‘We can do without lobsters, you know. Which shall sing?’",
1935
+    "‘Oh, YOU sing,’ said the Gryphon. ‘I’ve forgotten the words.’",
1936
+    "So they began solemnly dancing round and round Alice, every now and",
1937
+    "then treading on her toes when they passed too close, and waving their",
1938
+    "forepaws to mark the time, while the Mock Turtle sang this, very slowly",
1939
+    "and sadly:--",
1940
+    " ‘“Will you walk a little faster?” said a whiting to a snail.",
1941
+    " “There’s a porpoise close behind us, and he’s treading on my tail.",
1942
+    " See how eagerly the lobsters and the turtles all advance!",
1943
+    " They are waiting on the shingle--will you come and join the dance?",
1944
+    " Will you, won’t you, will you, won’t you, will you join the dance?",
1945
+    " Will you, won’t you, will you, won’t you, won’t you join the dance?",
1946
+    " “You can really have no notion how delightful it will be",
1947
+    " When they take us up and throw us, with the lobsters, out to sea!”",
1948
+    "  But the snail replied “Too far, too far!” and gave a look askance--",
1949
+    " Said he thanked the whiting kindly, but he would not join the dance.",
1950
+    " Would not, could not, would not, could not, would not join the dance.",
1951
+    " Would not, could not, would not, could not, could not join the dance.",
1952
+    " ‘“What matters it how far we go?” his scaly friend replied.",
1953
+    " “There is another shore, you know, upon the other side.",
1954
+    " The further off from England the nearer is to France--",
1955
+    " Then turn not pale, beloved snail, but come and join the dance.",
1956
+    " Will you, won’t you, will you, won’t you, will you join the dance?",
1957
+    " Will you, won’t you, will you, won’t you, won’t you join the dance?”’",
1958
+    "‘Thank you, it’s a very interesting dance to watch,’ said Alice, feeling",
1959
+    "very glad that it was over at last: ‘and I do so like that curious song",
1960
+    "about the whiting!’",
1961
+    "‘Oh, as to the whiting,’ said the Mock Turtle, ‘they--you’ve seen them,",
1962
+    "of course?’",
1963
+    "‘Yes,’ said Alice, ‘I’ve often seen them at dinn--’ she checked herself",
1964
+    "hastily.",
1965
+    "‘I don’t know where Dinn may be,’ said the Mock Turtle, ‘but if you’ve",
1966
+    "seen them so often, of course you know what they’re like.’",
1967
+    "‘I believe so,’ Alice replied thoughtfully. ‘They have their tails in",
1968
+    "their mouths--and they’re all over crumbs.’",
1969
+    "‘You’re wrong about the crumbs,’ said the Mock Turtle: ‘crumbs would all",
1970
+    "wash off in the sea. But they HAVE their tails in their mouths; and the",
1971
+    "reason is--’ here the Mock Turtle yawned and shut his eyes.--‘Tell her",
1972
+    "about the reason and all that,’ he said to the Gryphon.",
1973
+    "‘The reason is,’ said the Gryphon, ‘that they WOULD go with the lobsters",
1974
+    "to the dance. So they got thrown out to sea. So they had to fall a long",
1975
+    "way. So they got their tails fast in their mouths. So they couldn’t get",
1976
+    "them out again. That’s all.’",
1977
+    "‘Thank you,’ said Alice, ‘it’s very interesting. I never knew so much",
1978
+    "about a whiting before.’",
1979
+    "‘I can tell you more than that, if you like,’ said the Gryphon. ‘Do you",
1980
+    "know why it’s called a whiting?’",
1981
+    "‘I never thought about it,’ said Alice. ‘Why?’",
1982
+    "‘IT DOES THE BOOTS AND SHOES.’ the Gryphon replied very solemnly.",
1983
+    "Alice was thoroughly puzzled. ‘Does the boots and shoes!’ she repeated",
1984
+    "in a wondering tone.",
1985
+    "‘Why, what are YOUR shoes done with?’ said the Gryphon. ‘I mean, what",
1986
+    "makes them so shiny?’",
1987
+    "Alice looked down at them, and considered a little before she gave her",
1988
+    "answer. ‘They’re done with blacking, I believe.’",
1989
+    "‘Boots and shoes under the sea,’ the Gryphon went on in a deep voice,",
1990
+    "‘are done with a whiting. Now you know.’",
1991
+    "‘And what are they made of?’ Alice asked in a tone of great curiosity.",
1992
+    "‘Soles and eels, of course,’ the Gryphon replied rather impatiently:",
1993
+    "‘any shrimp could have told you that.’",
1994
+    "‘If I’d been the whiting,’ said Alice, whose thoughts were still running",
1995
+    "on the song, ‘I’d have said to the porpoise, “Keep back, please: we",
1996
+    "don’t want YOU with us!”’",
1997
+    "‘They were obliged to have him with them,’ the Mock Turtle said: ‘no",
1998
+    "wise fish would go anywhere without a porpoise.’",
1999
+    "‘Wouldn’t it really?’ said Alice in a tone of great surprise.",
2000
+    "‘Of course not,’ said the Mock Turtle: ‘why, if a fish came to ME, and",
2001
+    "told me he was going a journey, I should say “With what porpoise?”’",
2002
+    "‘Don’t you mean “purpose”?’ said Alice.",
2003
+    "‘I mean what I say,’ the Mock Turtle replied in an offended tone. And",
2004
+    "the Gryphon added ‘Come, let’s hear some of YOUR adventures.’",
2005
+    "‘I could tell you my adventures--beginning from this morning,’ said",
2006
+    "Alice a little timidly: ‘but it’s no use going back to yesterday,",
2007
+    "because I was a different person then.’",
2008
+    "‘Explain all that,’ said the Mock Turtle.",
2009
+    "‘No, no! The adventures first,’ said the Gryphon in an impatient tone:",
2010
+    "‘explanations take such a dreadful time.’",
2011
+    "So Alice began telling them her adventures from the time when she first",
2012
+    "saw the White Rabbit. She was a little nervous about it just at first,",
2013
+    "the two creatures got so close to her, one on each side, and opened",
2014
+    "their eyes and mouths so VERY wide, but she gained courage as she went",
2015
+    "on. Her listeners were perfectly quiet till she got to the part about",
2016
+    "her repeating ‘YOU ARE OLD, FATHER WILLIAM,’ to the Caterpillar, and the",
2017
+    "words all coming different, and then the Mock Turtle drew a long breath,",
2018
+    "and said ‘That’s very curious.’",
2019
+    "‘It’s all about as curious as it can be,’ said the Gryphon.",
2020
+    "‘It all came different!’ the Mock Turtle repeated thoughtfully. ‘I",
2021
+    "should like to hear her try and repeat something now. Tell her to",
2022
+    "begin.’ He looked at the Gryphon as if he thought it had some kind of",
2023
+    "authority over Alice.",
2024
+    "‘Stand up and repeat “‘TIS THE VOICE OF THE SLUGGARD,”’ said the",
2025
+    "Gryphon.",
2026
+    "‘How the creatures order one about, and make one repeat lessons!’",
2027
+    "thought Alice; ‘I might as well be at school at once.’ However, she",
2028
+    "got up, and began to repeat it, but her head was so full of the Lobster",
2029
+    "Quadrille, that she hardly knew what she was saying, and the words came",
2030
+    "very queer indeed:--",
2031
+    "  ‘’Tis the voice of the Lobster; I heard him declare,",
2032
+    "  “You have baked me too brown, I must sugar my hair.”",
2033
+    "   As a duck with its eyelids, so he with his nose",
2034
+    "  Trims his belt and his buttons, and turns out his toes.’",
2035
+    "       [later editions continued as follows",
2036
+    "  When the sands are all dry, he is gay as a lark,",
2037
+    "  And will talk in contemptuous tones of the Shark,",
2038
+    "  But, when the tide rises and sharks are around,",
2039
+    "  His voice has a timid and tremulous sound.]",
2040
+    "‘That’s different from what I used to say when I was a child,’ said the",
2041
+    "Gryphon.",
2042
+    "‘Well, I never heard it before,’ said the Mock Turtle; ‘but it sounds",
2043
+    "uncommon nonsense.’",
2044
+    "Alice said nothing; she had sat down with her face in her hands,",
2045
+    "wondering if anything would EVER happen in a natural way again.",
2046
+    "‘I should like to have it explained,’ said the Mock Turtle.",
2047
+    "‘She can’t explain it,’ said the Gryphon hastily. ‘Go on with the next",
2048
+    "verse.’",
2049
+    "‘But about his toes?’ the Mock Turtle persisted. ‘How COULD he turn them",
2050
+    "out with his nose, you know?’",
2051
+    "‘It’s the first position in dancing.’ Alice said; but was dreadfully",
2052
+    "puzzled by the whole thing, and longed to change the subject.",
2053
+    "‘Go on with the next verse,’ the Gryphon repeated impatiently: ‘it",
2054
+    "begins “I passed by his garden.”’",
2055
+    "Alice did not dare to disobey, though she felt sure it would all come",
2056
+    "wrong, and she went on in a trembling voice:--",
2057
+    "  ‘I passed by his garden, and marked, with one eye,",
2058
+    "  How the Owl and the Panther were sharing a pie--’",
2059
+    "    [later editions continued as follows",
2060
+    "  The Panther took pie-crust, and gravy, and meat,",
2061
+    "  While the Owl had the dish as its share of the treat.",
2062
+    "  When the pie was all finished, the Owl, as a boon,",
2063
+    "  Was kindly permitted to pocket the spoon:",
2064
+    "  While the Panther received knife and fork with a growl,",
2065
+    "  And concluded the banquet--]",
2066
+    "‘What IS the use of repeating all that stuff,’ the Mock Turtle",
2067
+    "interrupted, ‘if you don’t explain it as you go on? It’s by far the most",
2068
+    "confusing thing I ever heard!’",
2069
+    "‘Yes, I think you’d better leave off,’ said the Gryphon: and Alice was",
2070
+    "only too glad to do so.",
2071
+    "‘Shall we try another figure of the Lobster Quadrille?’ the Gryphon went",
2072
+    "on. ‘Or would you like the Mock Turtle to sing you a song?’",
2073
+    "‘Oh, a song, please, if the Mock Turtle would be so kind,’ Alice",
2074
+    "replied, so eagerly that the Gryphon said, in a rather offended tone,",
2075
+    "‘Hm! No accounting for tastes! Sing her “Turtle Soup,” will you, old",
2076
+    "fellow?’",
2077
+    "The Mock Turtle sighed deeply, and began, in a voice sometimes choked",
2078
+    "with sobs, to sing this:--",
2079
+    "   ‘Beautiful Soup, so rich and green,",
2080
+    "   Waiting in a hot tureen!",
2081
+    "   Who for such dainties would not stoop?",
2082
+    "   Soup of the evening, beautiful Soup!",
2083
+    "   Soup of the evening, beautiful Soup!",
2084
+    "     Beau--ootiful Soo--oop!",
2085
+    "     Beau--ootiful Soo--oop!",
2086
+    "   Soo--oop of the e--e--evening,",
2087
+    "     Beautiful, beautiful Soup!",
2088
+    "   ‘Beautiful Soup! Who cares for fish,",
2089
+    "   Game, or any other dish?",
2090
+    "   Who would not give all else for two",
2091
+    "   Pennyworth only of beautiful Soup?",
2092
+    "   Pennyworth only of beautiful Soup?",
2093
+    "     Beau--ootiful Soo--oop!",
2094
+    "     Beau--ootiful Soo--oop!",
2095
+    "   Soo--oop of the e--e--evening,",
2096
+    "     Beautiful, beauti--FUL SOUP!’",
2097
+    "‘Chorus again!’ cried the Gryphon, and the Mock Turtle had just begun",
2098
+    "to repeat it, when a cry of ‘The trial’s beginning!’ was heard in the",
2099
+    "distance.",
2100
+    "‘Come on!’ cried the Gryphon, and, taking Alice by the hand, it hurried",
2101
+    "off, without waiting for the end of the song.",
2102
+    "‘What trial is it?’ Alice panted as she ran; but the Gryphon only",
2103
+    "answered ‘Come on!’ and ran the faster, while more and more faintly",
2104
+    "came, carried on the breeze that followed them, the melancholy words:--",
2105
+    "   ‘Soo--oop of the e--e--evening,",
2106
+    "     Beautiful, beautiful Soup!’",
2107
+    "CHAPTER XI. Who Stole the Tarts?",
2108
+    "The King and Queen of Hearts were seated on their throne when they",
2109
+    "arrived, with a great crowd assembled about them--all sorts of little",
2110
+    "birds and beasts, as well as the whole pack of cards: the Knave was",
2111
+    "standing before them, in chains, with a soldier on each side to guard",
2112
+    "him; and near the King was the White Rabbit, with a trumpet in one hand,",
2113
+    "and a scroll of parchment in the other. In the very middle of the court",
2114
+    "was a table, with a large dish of tarts upon it: they looked so good,",
2115
+    "that it made Alice quite hungry to look at them--‘I wish they’d get the",
2116
+    "trial done,’ she thought, ‘and hand round the refreshments!’ But there",
2117
+    "seemed to be no chance of this, so she began looking at everything about",
2118
+    "her, to pass away the time.",
2119
+    "Alice had never been in a court of justice before, but she had read",
2120
+    "about them in books, and she was quite pleased to find that she knew",
2121
+    "the name of nearly everything there. ‘That’s the judge,’ she said to",
2122
+    "herself, ‘because of his great wig.’",
2123
+    "The judge, by the way, was the King; and as he wore his crown over the",
2124
+    "wig, (look at the frontispiece if you want to see how he did it,) he did",
2125
+    "not look at all comfortable, and it was certainly not becoming.",
2126
+    "‘And that’s the jury-box,’ thought Alice, ‘and those twelve creatures,’",
2127
+    "(she was obliged to say ‘creatures,’ you see, because some of them were",
2128
+    "animals, and some were birds,) ‘I suppose they are the jurors.’ She said",
2129
+    "this last word two or three times over to herself, being rather proud of",
2130
+    "it: for she thought, and rightly too, that very few little girls of her",
2131
+    "age knew the meaning of it at all. However, ‘jury-men’ would have done",
2132
+    "just as well.",
2133
+    "The twelve jurors were all writing very busily on slates. ‘What are they",
2134
+    "doing?’ Alice whispered to the Gryphon. ‘They can’t have anything to put",
2135
+    "down yet, before the trial’s begun.’",
2136
+    "‘They’re putting down their names,’ the Gryphon whispered in reply, ‘for",
2137
+    "fear they should forget them before the end of the trial.’",
2138
+    "‘Stupid things!’ Alice began in a loud, indignant voice, but she stopped",
2139
+    "hastily, for the White Rabbit cried out, ‘Silence in the court!’ and the",
2140
+    "King put on his spectacles and looked anxiously round, to make out who",
2141
+    "was talking.",
2142
+    "Alice could see, as well as if she were looking over their shoulders,",
2143
+    "that all the jurors were writing down ‘stupid things!’ on their slates,",
2144
+    "and she could even make out that one of them didn’t know how to spell",
2145
+    "‘stupid,’ and that he had to ask his neighbour to tell him. ‘A nice",
2146
+    "muddle their slates’ll be in before the trial’s over!’ thought Alice.",
2147
+    "One of the jurors had a pencil that squeaked. This of course, Alice",
2148
+    "could not stand, and she went round the court and got behind him, and",
2149
+    "very soon found an opportunity of taking it away. She did it so quickly",
2150
+    "that the poor little juror (it was Bill, the Lizard) could not make out",
2151
+    "at all what had become of it; so, after hunting all about for it, he was",
2152
+    "obliged to write with one finger for the rest of the day; and this was",
2153
+    "of very little use, as it left no mark on the slate.",
2154
+    "‘Herald, read the accusation!’ said the King.",
2155
+    "On this the White Rabbit blew three blasts on the trumpet, and then",
2156
+    "unrolled the parchment scroll, and read as follows:--",
2157
+    "   ‘The Queen of Hearts, she made some tarts,",
2158
+    "      All on a summer day:",
2159
+    "    The Knave of Hearts, he stole those tarts,",
2160
+    "      And took them quite away!’",
2161
+    "‘Consider your verdict,’ the King said to the jury.",
2162
+    "‘Not yet, not yet!’ the Rabbit hastily interrupted. ‘There’s a great",
2163
+    "deal to come before that!’",
2164
+    "‘Call the first witness,’ said the King; and the White Rabbit blew three",
2165
+    "blasts on the trumpet, and called out, ‘First witness!’",
2166
+    "The first witness was the Hatter. He came in with a teacup in one",
2167
+    "hand and a piece of bread-and-butter in the other. ‘I beg pardon, your",
2168
+    "Majesty,’ he began, ‘for bringing these in: but I hadn’t quite finished",
2169
+    "my tea when I was sent for.’",
2170
+    "‘You ought to have finished,’ said the King. ‘When did you begin?’",
2171
+    "The Hatter looked at the March Hare, who had followed him into the",
2172
+    "court, arm-in-arm with the Dormouse. ‘Fourteenth of March, I think it",
2173
+    "was,’ he said.",
2174
+    "‘Fifteenth,’ said the March Hare.",
2175
+    "‘Sixteenth,’ added the Dormouse.",
2176
+    "‘Write that down,’ the King said to the jury, and the jury eagerly",
2177
+    "wrote down all three dates on their slates, and then added them up, and",
2178
+    "reduced the answer to shillings and pence.",
2179
+    "‘Take off your hat,’ the King said to the Hatter.",
2180
+    "‘It isn’t mine,’ said the Hatter.",
2181
+    "‘Stolen!’ the King exclaimed, turning to the jury, who instantly made a",
2182
+    "memorandum of the fact.",
2183
+    "‘I keep them to sell,’ the Hatter added as an explanation; ‘I’ve none of",
2184
+    "my own. I’m a hatter.’",
2185
+    "Here the Queen put on her spectacles, and began staring at the Hatter,",
2186
+    "who turned pale and fidgeted.",
2187
+    "‘Give your evidence,’ said the King; ‘and don’t be nervous, or I’ll have",
2188
+    "you executed on the spot.’",
2189
+    "This did not seem to encourage the witness at all: he kept shifting",
2190
+    "from one foot to the other, looking uneasily at the Queen, and in",
2191
+    "his confusion he bit a large piece out of his teacup instead of the",
2192
+    "bread-and-butter.",
2193
+    "Just at this moment Alice felt a very curious sensation, which puzzled",
2194
+    "her a good deal until she made out what it was: she was beginning to",
2195
+    "grow larger again, and she thought at first she would get up and leave",
2196
+    "the court; but on second thoughts she decided to remain where she was as",
2197
+    "long as there was room for her.",
2198
+    "‘I wish you wouldn’t squeeze so.’ said the Dormouse, who was sitting",
2199
+    "next to her. ‘I can hardly breathe.’",
2200
+    "‘I can’t help it,’ said Alice very meekly: ‘I’m growing.’",
2201
+    "‘You’ve no right to grow here,’ said the Dormouse.",
2202
+    "‘Don’t talk nonsense,’ said Alice more boldly: ‘you know you’re growing",
2203
+    "too.’",
2204
+    "‘Yes, but I grow at a reasonable pace,’ said the Dormouse: ‘not in that",
2205
+    "ridiculous fashion.’ And he got up very sulkily and crossed over to the",
2206
+    "other side of the court.",
2207
+    "All this time the Queen had never left off staring at the Hatter, and,",
2208
+    "just as the Dormouse crossed the court, she said to one of the officers",
2209
+    "of the court, ‘Bring me the list of the singers in the last concert!’ on",
2210
+    "which the wretched Hatter trembled so, that he shook both his shoes off.",
2211
+    "‘Give your evidence,’ the King repeated angrily, ‘or I’ll have you",
2212
+    "executed, whether you’re nervous or not.’",
2213
+    "‘I’m a poor man, your Majesty,’ the Hatter began, in a trembling voice,",
2214
+    "‘--and I hadn’t begun my tea--not above a week or so--and what with the",
2215
+    "bread-and-butter getting so thin--and the twinkling of the tea--’",
2216
+    "‘The twinkling of the what?’ said the King.",
2217
+    "‘It began with the tea,’ the Hatter replied.",
2218
+    "‘Of course twinkling begins with a T!’ said the King sharply. ‘Do you",
2219
+    "take me for a dunce? Go on!’",
2220
+    "‘I’m a poor man,’ the Hatter went on, ‘and most things twinkled after",
2221
+    "that--only the March Hare said--’",
2222
+    "‘I didn’t!’ the March Hare interrupted in a great hurry.",
2223
+    "‘You did!’ said the Hatter.",
2224
+    "‘I deny it!’ said the March Hare.",
2225
+    "‘He denies it,’ said the King: ‘leave out that part.’",
2226
+    "‘Well, at any rate, the Dormouse said--’ the Hatter went on, looking",
2227
+    "anxiously round to see if he would deny it too: but the Dormouse denied",
2228
+    "nothing, being fast asleep.",
2229
+    "‘After that,’ continued the Hatter, ‘I cut some more bread-and-butter--’",
2230
+    "‘But what did the Dormouse say?’ one of the jury asked.",
2231
+    "‘That I can’t remember,’ said the Hatter.",
2232
+    "‘You MUST remember,’ remarked the King, ‘or I’ll have you executed.’",
2233
+    "The miserable Hatter dropped his teacup and bread-and-butter, and went",
2234
+    "down on one knee. ‘I’m a poor man, your Majesty,’ he began.",
2235
+    "‘You’re a very poor speaker,’ said the King.",
2236
+    "Here one of the guinea-pigs cheered, and was immediately suppressed by",
2237
+    "the officers of the court. (As that is rather a hard word, I will just",
2238
+    "explain to you how it was done. They had a large canvas bag, which tied",
2239
+    "up at the mouth with strings: into this they slipped the guinea-pig,",
2240
+    "head first, and then sat upon it.)",
2241
+    "‘I’m glad I’ve seen that done,’ thought Alice. ‘I’ve so often read",
2242
+    "in the newspapers, at the end of trials, “There was some attempts",
2243
+    "at applause, which was immediately suppressed by the officers of the",
2244
+    "court,” and I never understood what it meant till now.’",
2245
+    "‘If that’s all you know about it, you may stand down,’ continued the",
2246
+    "King.",
2247
+    "‘I can’t go no lower,’ said the Hatter: ‘I’m on the floor, as it is.’",
2248
+    "‘Then you may SIT down,’ the King replied.",
2249
+    "Here the other guinea-pig cheered, and was suppressed.",
2250
+    "‘Come, that finished the guinea-pigs!’ thought Alice. ‘Now we shall get",
2251
+    "on better.’",
2252
+    "‘I’d rather finish my tea,’ said the Hatter, with an anxious look at the",
2253
+    "Queen, who was reading the list of singers.",
2254
+    "‘You may go,’ said the King, and the Hatter hurriedly left the court,",
2255
+    "without even waiting to put his shoes on.",
2256
+    "‘--and just take his head off outside,’ the Queen added to one of the",
2257
+    "officers: but the Hatter was out of sight before the officer could get",
2258
+    "to the door.",
2259
+    "‘Call the next witness!’ said the King.",
2260
+    "The next witness was the Duchess’s cook. She carried the pepper-box in",
2261
+    "her hand, and Alice guessed who it was, even before she got into the",
2262
+    "court, by the way the people near the door began sneezing all at once.",
2263
+    "‘Give your evidence,’ said the King.",
2264
+    "‘Shan’t,’ said the cook.",
2265
+    "The King looked anxiously at the White Rabbit, who said in a low voice,",
2266
+    "‘Your Majesty must cross-examine THIS witness.’",
2267
+    "‘Well, if I must, I must,’ the King said, with a melancholy air, and,",
2268
+    "after folding his arms and frowning at the cook till his eyes were",
2269
+    "nearly out of sight, he said in a deep voice, ‘What are tarts made of?’",
2270
+    "‘Pepper, mostly,’ said the cook.",
2271
+    "‘Treacle,’ said a sleepy voice behind her.",
2272
+    "‘Collar that Dormouse,’ the Queen shrieked out. ‘Behead that Dormouse!",
2273
+    "Turn that Dormouse out of court! Suppress him! Pinch him! Off with his",
2274
+    "whiskers!’",
2275
+    "For some minutes the whole court was in confusion, getting the Dormouse",
2276
+    "turned out, and, by the time they had settled down again, the cook had",
2277
+    "disappeared.",
2278
+    "‘Never mind!’ said the King, with an air of great relief. ‘Call the next",
2279
+    "witness.’ And he added in an undertone to the Queen, ‘Really, my dear,",
2280
+    "YOU must cross-examine the next witness. It quite makes my forehead",
2281
+    "ache!’",
2282
+    "Alice watched the White Rabbit as he fumbled over the list, feeling very",
2283
+    "curious to see what the next witness would be like, ‘--for they haven’t",
2284
+    "got much evidence YET,’ she said to herself. Imagine her surprise, when",
2285
+    "the White Rabbit read out, at the top of his shrill little voice, the",
2286
+    "name ‘Alice!’",
2287
+    "CHAPTER XII. Alice’s Evidence",
2288
+    "‘Here!’ cried Alice, quite forgetting in the flurry of the moment how",
2289
+    "large she had grown in the last few minutes, and she jumped up in such",
2290
+    "a hurry that she tipped over the jury-box with the edge of her skirt,",
2291
+    "upsetting all the jurymen on to the heads of the crowd below, and there",
2292
+    "they lay sprawling about, reminding her very much of a globe of goldfish",
2293
+    "she had accidentally upset the week before.",
2294
+    "‘Oh, I BEG your pardon!’ she exclaimed in a tone of great dismay, and",
2295
+    "began picking them up again as quickly as she could, for the accident of",
2296
+    "the goldfish kept running in her head, and she had a vague sort of idea",
2297
+    "that they must be collected at once and put back into the jury-box, or",
2298
+    "they would die.",
2299
+    "‘The trial cannot proceed,’ said the King in a very grave voice, ‘until",
2300
+    "all the jurymen are back in their proper places--ALL,’ he repeated with",
2301
+    "great emphasis, looking hard at Alice as he said do.",
2302
+    "Alice looked at the jury-box, and saw that, in her haste, she had put",
2303
+    "the Lizard in head downwards, and the poor little thing was waving its",
2304
+    "tail about in a melancholy way, being quite unable to move. She soon got",
2305
+    "it out again, and put it right; ‘not that it signifies much,’ she said",
2306
+    "to herself; ‘I should think it would be QUITE as much use in the trial",
2307
+    "one way up as the other.’",
2308
+    "As soon as the jury had a little recovered from the shock of being",
2309
+    "upset, and their slates and pencils had been found and handed back to",
2310
+    "them, they set to work very diligently to write out a history of the",
2311
+    "accident, all except the Lizard, who seemed too much overcome to do",
2312
+    "anything but sit with its mouth open, gazing up into the roof of the",
2313
+    "court.",
2314
+    "‘What do you know about this business?’ the King said to Alice.",
2315
+    "‘Nothing,’ said Alice.",
2316
+    "‘Nothing WHATEVER?’ persisted the King.",
2317
+    "‘Nothing whatever,’ said Alice.",
2318
+    "‘That’s very important,’ the King said, turning to the jury. They were",
2319
+    "just beginning to write this down on their slates, when the White Rabbit",
2320
+    "interrupted: ‘UNimportant, your Majesty means, of course,’ he said in a",
2321
+    "very respectful tone, but frowning and making faces at him as he spoke.",
2322
+    "‘UNimportant, of course, I meant,’ the King hastily said, and went on",
2323
+    "to himself in an undertone,",
2324
+    "‘important--unimportant--unimportant--important--’ as if he were trying",
2325
+    "which word sounded best.",
2326
+    "Some of the jury wrote it down ‘important,’ and some ‘unimportant.’",
2327
+    "Alice could see this, as she was near enough to look over their slates;",
2328
+    "‘but it doesn’t matter a bit,’ she thought to herself.",
2329
+    "At this moment the King, who had been for some time busily writing in",
2330
+    "his note-book, cackled out ‘Silence!’ and read out from his book, ‘Rule",
2331
+    "Forty-two. ALL PERSONS MORE THAN A MILE HIGH TO LEAVE THE COURT.’",
2332
+    "Everybody looked at Alice.",
2333
+    "‘I’M not a mile high,’ said Alice.",
2334
+    "‘You are,’ said the King.",
2335
+    "‘Nearly two miles high,’ added the Queen.",
2336
+    "‘Well, I shan’t go, at any rate,’ said Alice: ‘besides, that’s not a",
2337
+    "regular rule: you invented it just now.’",
2338
+    "‘It’s the oldest rule in the book,’ said the King.",
2339
+    "‘Then it ought to be Number One,’ said Alice.",
2340
+    "The King turned pale, and shut his note-book hastily. ‘Consider your",
2341
+    "verdict,’ he said to the jury, in a low, trembling voice.",
2342
+    "‘There’s more evidence to come yet, please your Majesty,’ said the White",
2343
+    "Rabbit, jumping up in a great hurry; ‘this paper has just been picked",
2344
+    "up.’",
2345
+    "‘What’s in it?’ said the Queen.",
2346
+    "‘I haven’t opened it yet,’ said the White Rabbit, ‘but it seems to be a",
2347
+    "letter, written by the prisoner to--to somebody.’",
2348
+    "‘It must have been that,’ said the King, ‘unless it was written to",
2349
+    "nobody, which isn’t usual, you know.’",
2350
+    "‘Who is it directed to?’ said one of the jurymen.",
2351
+    "‘It isn’t directed at all,’ said the White Rabbit; ‘in fact, there’s",
2352
+    "nothing written on the OUTSIDE.’ He unfolded the paper as he spoke, and",
2353
+    "added ‘It isn’t a letter, after all: it’s a set of verses.’",
2354
+    "‘Are they in the prisoner’s handwriting?’ asked another of the jurymen.",
2355
+    "‘No, they’re not,’ said the White Rabbit, ‘and that’s the queerest thing",
2356
+    "about it.’ (The jury all looked puzzled.)",
2357
+    "‘He must have imitated somebody else’s hand,’ said the King. (The jury",
2358
+    "all brightened up again.)",
2359
+    "‘Please your Majesty,’ said the Knave, ‘I didn’t write it, and they",
2360
+    "can’t prove I did: there’s no name signed at the end.’",
2361
+    "‘If you didn’t sign it,’ said the King, ‘that only makes the matter",
2362
+    "worse. You MUST have meant some mischief, or else you’d have signed your",
2363
+    "name like an honest man.’",
2364
+    "There was a general clapping of hands at this: it was the first really",
2365
+    "clever thing the King had said that day.",
2366
+    "‘That PROVES his guilt,’ said the Queen.",
2367
+    "‘It proves nothing of the sort!’ said Alice. ‘Why, you don’t even know",
2368
+    "what they’re about!’",
2369
+    "‘Read them,’ said the King.",
2370
+    "The White Rabbit put on his spectacles. ‘Where shall I begin, please",
2371
+    "your Majesty?’ he asked.",
2372
+    "‘Begin at the beginning,’ the King said gravely, ‘and go on till you",
2373
+    "come to the end: then stop.’",
2374
+    "These were the verses the White Rabbit read:--",
2375
+    "   ‘They told me you had been to her,",
2376
+    "    And mentioned me to him:",
2377
+    "   She gave me a good character,",
2378
+    "    But said I could not swim.",
2379
+    "   He sent them word I had not gone",
2380
+    "    (We know it to be true):",
2381
+    "   If she should push the matter on,",
2382
+    "    What would become of you?",
2383
+    "   I gave her one, they gave him two,",
2384
+    "    You gave us three or more;",
2385
+    "   They all returned from him to you,",
2386
+    "    Though they were mine before.",
2387
+    "   If I or she should chance to be",
2388
+    "    Involved in this affair,",
2389
+    "   He trusts to you to set them free,",
2390
+    "    Exactly as we were.",
2391
+    "   My notion was that you had been",
2392
+    "    (Before she had this fit)",
2393
+    "   An obstacle that came between",
2394
+    "    Him, and ourselves, and it.",
2395
+    "   Don’t let him know she liked them best,",
2396
+    "    For this must ever be",
2397
+    "   A secret, kept from all the rest,",
2398
+    "    Between yourself and me.’",
2399
+    "‘That’s the most important piece of evidence we’ve heard yet,’ said the",
2400
+    "King, rubbing his hands; ‘so now let the jury--’",
2401
+    "‘If any one of them can explain it,’ said Alice, (she had grown so large",
2402
+    "in the last few minutes that she wasn’t a bit afraid of interrupting",
2403
+    "him,) ‘I’ll give him sixpence. _I_ don’t believe there’s an atom of",
2404
+    "meaning in it.’",
2405
+    "The jury all wrote down on their slates, ‘SHE doesn’t believe there’s an",
2406
+    "atom of meaning in it,’ but none of them attempted to explain the paper.",
2407
+    "‘If there’s no meaning in it,’ said the King, ‘that saves a world of",
2408
+    "trouble, you know, as we needn’t try to find any. And yet I don’t know,’",
2409
+    "he went on, spreading out the verses on his knee, and looking at them",
2410
+    "with one eye; ‘I seem to see some meaning in them, after all. “--SAID",
2411
+    "I COULD NOT SWIM--” you can’t swim, can you?’ he added, turning to the",
2412
+    "Knave.",
2413
+    "The Knave shook his head sadly. ‘Do I look like it?’ he said. (Which he",
2414
+    "certainly did NOT, being made entirely of cardboard.)",
2415
+    "‘All right, so far,’ said the King, and he went on muttering over",
2416
+    "the verses to himself: ‘“WE KNOW IT TO BE TRUE--” that’s the jury, of",
2417
+    "course--“I GAVE HER ONE, THEY GAVE HIM TWO--” why, that must be what he",
2418
+    "did with the tarts, you know--’",
2419
+    "‘But, it goes on “THEY ALL RETURNED FROM HIM TO YOU,”’ said Alice.",
2420
+    "‘Why, there they are!’ said the King triumphantly, pointing to the tarts",
2421
+    "on the table. ‘Nothing can be clearer than THAT. Then again--“BEFORE SHE",
2422
+    "HAD THIS FIT--” you never had fits, my dear, I think?’ he said to the",
2423
+    "Queen.",
2424
+    "‘Never!’ said the Queen furiously, throwing an inkstand at the Lizard",
2425
+    "as she spoke. (The unfortunate little Bill had left off writing on his",
2426
+    "slate with one finger, as he found it made no mark; but he now hastily",
2427
+    "began again, using the ink, that was trickling down his face, as long as",
2428
+    "it lasted.)",
2429
+    "‘Then the words don’t FIT you,’ said the King, looking round the court",
2430
+    "with a smile. There was a dead silence.",
2431
+    "‘It’s a pun!’ the King added in an offended tone, and everybody laughed,",
2432
+    "‘Let the jury consider their verdict,’ the King said, for about the",
2433
+    "twentieth time that day.",
2434
+    "‘No, no!’ said the Queen. ‘Sentence first--verdict afterwards.’",
2435
+    "‘Stuff and nonsense!’ said Alice loudly. ‘The idea of having the",
2436
+    "sentence first!’",
2437
+    "‘Hold your tongue!’ said the Queen, turning purple.",
2438
+    "‘I won’t!’ said Alice.",
2439
+    "‘Off with her head!’ the Queen shouted at the top of her voice. Nobody",
2440
+    "moved.",
2441
+    "‘Who cares for you?’ said Alice, (she had grown to her full size by this",
2442
+    "time.) ‘You’re nothing but a pack of cards!’",
2443
+    "At this the whole pack rose up into the air, and came flying down upon",
2444
+    "her: she gave a little scream, half of fright and half of anger, and",
2445
+    "tried to beat them off, and found herself lying on the bank, with her",
2446
+    "head in the lap of her sister, who was gently brushing away some dead",
2447
+    "leaves that had fluttered down from the trees upon her face.",
2448
+    "‘Wake up, Alice dear!’ said her sister; ‘Why, what a long sleep you’ve",
2449
+    "had!’",
2450
+    "‘Oh, I’ve had such a curious dream!’ said Alice, and she told her",
2451
+    "sister, as well as she could remember them, all these strange Adventures",
2452
+    "of hers that you have just been reading about; and when she had",
2453
+    "finished, her sister kissed her, and said, ‘It WAS a curious dream,",
2454
+    "dear, certainly: but now run in to your tea; it’s getting late.’ So",
2455
+    "Alice got up and ran off, thinking while she ran, as well she might,",
2456
+    "what a wonderful dream it had been.",
2457
+    "But her sister sat still just as she left her, leaning her head on her",
2458
+    "hand, watching the setting sun, and thinking of little Alice and all her",
2459
+    "wonderful Adventures, till she too began dreaming after a fashion, and",
2460
+    "this was her dream:--",
2461
+    "First, she dreamed of little Alice herself, and once again the tiny",
2462
+    "hands were clasped upon her knee, and the bright eager eyes were looking",
2463
+    "up into hers--she could hear the very tones of her voice, and see that",
2464
+    "queer little toss of her head to keep back the wandering hair that",
2465
+    "WOULD always get into her eyes--and still as she listened, or seemed to",
2466
+    "listen, the whole place around her became alive with the strange creatures",
2467
+    "of her little sister’s dream.",
2468
+    "The long grass rustled at her feet as the White Rabbit hurried by--the",
2469
+    "frightened Mouse splashed his way through the neighbouring pool--she",
2470
+    "could hear the rattle of the teacups as the March Hare and his friends",
2471
+    "shared their never-ending meal, and the shrill voice of the Queen",
2472
+    "ordering off her unfortunate guests to execution--once more the pig-baby",
2473
+    "was sneezing on the Duchess’s knee, while plates and dishes crashed",
2474
+    "around it--once more the shriek of the Gryphon, the squeaking of the",
2475
+    "Lizard’s slate-pencil, and the choking of the suppressed guinea-pigs,",
2476
+    "filled the air, mixed up with the distant sobs of the miserable Mock",
2477
+    "Turtle.",
2478
+    "So she sat on, with closed eyes, and half believed herself in",
2479
+    "Wonderland, though she knew she had but to open them again, and all",
2480
+    "would change to dull reality--the grass would be only rustling in the",
2481
+    "wind, and the pool rippling to the waving of the reeds--the rattling",
2482
+    "teacups would change to tinkling sheep-bells, and the Queen’s shrill",
2483
+    "cries to the voice of the shepherd boy--and the sneeze of the baby, the",
2484
+    "shriek of the Gryphon, and all the other queer noises, would change (she",
2485
+    "knew) to the confused clamour of the busy farm-yard--while the lowing",
2486
+    "of the cattle in the distance would take the place of the Mock Turtle’s",
2487
+    "heavy sobs.",
2488
+    "Lastly, she pictured to herself how this same little sister of hers",
2489
+    "would, in the after-time, be herself a grown woman; and how she would",
2490
+    "keep, through all her riper years, the simple and loving heart of her",
2491
+    "childhood: and how she would gather about her other little children, and",
2492
+    "make THEIR eyes bright and eager with many a strange tale, perhaps even",
2493
+    "with the dream of Wonderland of long ago: and how she would feel with",
2494
+    "all their simple sorrows, and find a pleasure in all their simple joys,",
2495
+    "remembering her own child-life, and the happy summer days.",
2496
+    "              THE END",
2497
+    "End of Project Gutenberg’s Alice’s Adventures in Wonderland, by Lewis Carroll",
2498
+    "*** END OF THIS PROJECT GUTENBERG EBOOK ALICE’S ADVENTURES IN WONDERLAND ***",
2499
+    "***** This file should be named 11-0.txt or 11-0.zip *****",
2500
+    "This and all associated files of various formats will be found in:",
2501
+    "        http://www.gutenberg.org/1/11/",
2502
+    "Updated editions will replace the previous one--the old editions",
2503
+    "will be renamed.",
2504
+    "Creating the works from public domain print editions means that no",
2505
+    "one owns a United States copyright in these works, so the Foundation",
2506
+    "(and you!) can copy and distribute it in the United States without",
2507
+    "permission and without paying copyright royalties.  Special rules,",
2508
+    "set forth in the General Terms of Use part of this license, apply to",
2509
+    "copying and distributing Project Gutenberg-tm electronic works to",
2510
+    "protect the PROJECT GUTENBERG-tm concept and trademark.  Project",
2511
+    "Gutenberg is a registered trademark, and may not be used if you",
2512
+    "charge for the eBooks, unless you receive specific permission.  If you",
2513
+    "do not charge anything for copies of this eBook, complying with the",
2514
+    "rules is very easy.  You may use this eBook for nearly any purpose",
2515
+    "such as creation of derivative works, reports, performances and",
2516
+    "research.  They may be modified and printed and given away--you may do",
2517
+    "practically ANYTHING with public domain eBooks.  Redistribution is",
2518
+    "subject to the trademark license, especially commercial",
2519
+    "redistribution.",
2520
+    "*** START: FULL LICENSE ***",
2521
+    "THE FULL PROJECT GUTENBERG LICENSE",
2522
+    "PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK",
2523
+    "To protect the Project Gutenberg-tm mission of promoting the free",
2524
+    "distribution of electronic works, by using or distributing this work",
2525
+    "(or any other work associated in any way with the phrase “Project",
2526
+    "Gutenberg”), you agree to comply with all the terms of the Full Project",
2527
+    "Gutenberg-tm License (available with this file or online at",
2528
+    "http://gutenberg.org/license).",
2529
+    "Section 1.  General Terms of Use and Redistributing Project Gutenberg-tm",
2530
+    "electronic works",
2531
+    "1.A.  By reading or using any part of this Project Gutenberg-tm",
2532
+    "electronic work, you indicate that you have read, understand, agree to",
2533
+    "and accept all the terms of this license and intellectual property",
2534
+    "(trademark/copyright) agreement.  If you do not agree to abide by all",
2535
+    "the terms of this agreement, you must cease using and return or destroy",
2536
+    "all copies of Project Gutenberg-tm electronic works in your possession.",
2537
+    "If you paid a fee for obtaining a copy of or access to a Project",
2538
+    "Gutenberg-tm electronic work and you do not agree to be bound by the",
2539
+    "terms of this agreement, you may obtain a refund from the person or",
2540
+    "entity to whom you paid the fee as set forth in paragraph 1.E.8.",
2541
+    "1.B.  “Project Gutenberg” is a registered trademark.  It may only be",
2542
+    "used on or associated in any way with an electronic work by people who",
2543
+    "agree to be bound by the terms of this agreement.  There are a few",
2544
+    "things that you can do with most Project Gutenberg-tm electronic works",
2545
+    "even without complying with the full terms of this agreement.  See",
2546
+    "paragraph 1.C below.  There are a lot of things you can do with Project",
2547
+    "Gutenberg-tm electronic works if you follow the terms of this agreement",
2548
+    "and help preserve free future access to Project Gutenberg-tm electronic",
2549
+    "works.  See paragraph 1.E below.",
2550
+    "1.C.  The Project Gutenberg Literary Archive Foundation (“the Foundation”",
2551
+    " or PGLAF), owns a compilation copyright in the collection of Project",
2552
+    "Gutenberg-tm electronic works.  Nearly all the individual works in the",
2553
+    "collection are in the public domain in the United States.  If an",
2554
+    "individual work is in the public domain in the United States and you are",
2555
+    "located in the United States, we do not claim a right to prevent you from",
2556
+    "copying, distributing, performing, displaying or creating derivative",
2557
+    "works based on the work as long as all references to Project Gutenberg",
2558
+    "are removed.  Of course, we hope that you will support the Project",
2559
+    "Gutenberg-tm mission of promoting free access to electronic works by",
2560
+    "freely sharing Project Gutenberg-tm works in compliance with the terms of",
2561
+    "this agreement for keeping the Project Gutenberg-tm name associated with",
2562
+    "the work.  You can easily comply with the terms of this agreement by",
2563
+    "keeping this work in the same format with its attached full Project",
2564
+    "Gutenberg-tm License when you share it without charge with others.",
2565
+    "1.D.  The copyright laws of the place where you are located also govern",
2566
+    "what you can do with this work.  Copyright laws in most countries are in",
2567
+    "a constant state of change.  If you are outside the United States, check",
2568
+    "the laws of your country in addition to the terms of this agreement",
2569
+    "before downloading, copying, displaying, performing, distributing or",
2570
+    "creating derivative works based on this work or any other Project",
2571
+    "Gutenberg-tm work.  The Foundation makes no representations concerning",
2572
+    "the copyright status of any work in any country outside the United",
2573
+    "States.",
2574
+    "1.E.  Unless you have removed all references to Project Gutenberg:",
2575
+    "1.E.1.  The following sentence, with active links to, or other immediate",
2576
+    "access to, the full Project Gutenberg-tm License must appear prominently",
2577
+    "whenever any copy of a Project Gutenberg-tm work (any work on which the",
2578
+    "phrase “Project Gutenberg” appears, or with which the phrase “Project",
2579
+    "Gutenberg” is associated) is accessed, displayed, performed, viewed,",
2580
+    "copied or distributed:",
2581
+    "This eBook is for the use of anyone anywhere at no cost and with",
2582
+    "almost no restrictions whatsoever.  You may copy it, give it away or",
2583
+    "re-use it under the terms of the Project Gutenberg License included",
2584
+    "with this eBook or online at www.gutenberg.org",
2585
+    "1.E.2.  If an individual Project Gutenberg-tm electronic work is derived",
2586
+    "from the public domain (does not contain a notice indicating that it is",
2587
+    "posted with permission of the copyright holder), the work can be copied",
2588
+    "and distributed to anyone in the United States without paying any fees",
2589
+    "or charges.  If you are redistributing or providing access to a work",
2590
+    "with the phrase “Project Gutenberg” associated with or appearing on the",
2591
+    "work, you must comply either with the requirements of paragraphs 1.E.1",
2592
+    "through 1.E.7 or obtain permission for the use of the work and the",
2593
+    "Project Gutenberg-tm trademark as set forth in paragraphs 1.E.8 or",
2594
+    "1.E.9.",
2595
+    "1.E.3.  If an individual Project Gutenberg-tm electronic work is posted",
2596
+    "with the permission of the copyright holder, your use and distribution",
2597
+    "must comply with both paragraphs 1.E.1 through 1.E.7 and any additional",
2598
+    "terms imposed by the copyright holder.  Additional terms will be linked",
2599
+    "to the Project Gutenberg-tm License for all works posted with the",
2600
+    "permission of the copyright holder found at the beginning of this work.",
2601
+    "1.E.4.  Do not unlink or detach or remove the full Project Gutenberg-tm",
2602
+    "License terms from this work, or any files containing a part of this",
2603
+    "work or any other work associated with Project Gutenberg-tm.",
2604
+    "1.E.5.  Do not copy, display, perform, distribute or redistribute this",
2605
+    "electronic work, or any part of this electronic work, without",
2606
+    "prominently displaying the sentence set forth in paragraph 1.E.1 with",
2607
+    "active links or immediate access to the full terms of the Project",
2608
+    "Gutenberg-tm License.",
2609
+    "1.E.6.  You may convert to and distribute this work in any binary,",
2610
+    "compressed, marked up, nonproprietary or proprietary form, including any",
2611
+    "word processing or hypertext form.  However, if you provide access to or",
2612
+    "distribute copies of a Project Gutenberg-tm work in a format other than",
2613
+    "“Plain Vanilla ASCII” or other format used in the official version",
2614
+    "posted on the official Project Gutenberg-tm web site (www.gutenberg.org),",
2615
+    "you must, at no additional cost, fee or expense to the user, provide a",
2616
+    "copy, a means of exporting a copy, or a means of obtaining a copy upon",
2617
+    "request, of the work in its original “Plain Vanilla ASCII” or other",
2618
+    "form.  Any alternate format must include the full Project Gutenberg-tm",
2619
+    "License as specified in paragraph 1.E.1.",
2620
+    "1.E.7.  Do not charge a fee for access to, viewing, displaying,",
2621
+    "performing, copying or distributing any Project Gutenberg-tm works",
2622
+    "unless you comply with paragraph 1.E.8 or 1.E.9.",
2623
+    "1.E.8.  You may charge a reasonable fee for copies of or providing",
2624
+    "access to or distributing Project Gutenberg-tm electronic works provided",
2625
+    "that",
2626
+    "- You pay a royalty fee of 20% of the gross profits you derive from",
2627
+    "     the use of Project Gutenberg-tm works calculated using the method",
2628
+    "     you already use to calculate your applicable taxes.  The fee is",
2629
+    "     owed to the owner of the Project Gutenberg-tm trademark, but he",
2630
+    "     has agreed to donate royalties under this paragraph to the",
2631
+    "     Project Gutenberg Literary Archive Foundation.  Royalty payments",
2632
+    "     must be paid within 60 days following each date on which you",
2633
+    "     prepare (or are legally required to prepare) your periodic tax",
2634
+    "     returns.  Royalty payments should be clearly marked as such and",
2635
+    "     sent to the Project Gutenberg Literary Archive Foundation at the",
2636
+    "     address specified in Section 4, “Information about donations to",
2637
+    "     the Project Gutenberg Literary Archive Foundation.”",
2638
+    "- You provide a full refund of any money paid by a user who notifies",
2639
+    "     you in writing (or by e-mail) within 30 days of receipt that s/he",
2640
+    "     does not agree to the terms of the full Project Gutenberg-tm",
2641
+    "     License.  You must require such a user to return or",
2642
+    "     destroy all copies of the works possessed in a physical medium",
2643
+    "     and discontinue all use of and all access to other copies of",
2644
+    "     Project Gutenberg-tm works.",
2645
+    "- You provide, in accordance with paragraph 1.F.3, a full refund of any",
2646
+    "     money paid for a work or a replacement copy, if a defect in the",
2647
+    "     electronic work is discovered and reported to you within 90 days",
2648
+    "     of receipt of the work.",
2649
+    "- You comply with all other terms of this agreement for free",
2650
+    "     distribution of Project Gutenberg-tm works.",
2651
+    "1.E.9.  If you wish to charge a fee or distribute a Project Gutenberg-tm",
2652
+    "electronic work or group of works on different terms than are set",
2653
+    "forth in this agreement, you must obtain permission in writing from",
2654
+    "both the Project Gutenberg Literary Archive Foundation and Michael",
2655
+    "Hart, the owner of the Project Gutenberg-tm trademark.  Contact the",
2656
+    "Foundation as set forth in Section 3 below.",
2657
+    "1.F.",
2658
+    "1.F.1.  Project Gutenberg volunteers and employees expend considerable",
2659
+    "effort to identify, do copyright research on, transcribe and proofread",
2660
+    "public domain works in creating the Project Gutenberg-tm",
2661
+    "collection.  Despite these efforts, Project Gutenberg-tm electronic",
2662
+    "works, and the medium on which they may be stored, may contain",
2663
+    "“Defects,” such as, but not limited to, incomplete, inaccurate or",
2664
+    "corrupt data, transcription errors, a copyright or other intellectual",
2665
+    "property infringement, a defective or damaged disk or other medium, a",
2666
+    "computer virus, or computer codes that damage or cannot be read by",
2667
+    "your equipment.",
2668
+    "1.F.2.  LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for the “Right",
2669
+    "of Replacement or Refund” described in paragraph 1.F.3, the Project",
2670
+    "Gutenberg Literary Archive Foundation, the owner of the Project",
2671
+    "Gutenberg-tm trademark, and any other party distributing a Project",
2672
+    "Gutenberg-tm electronic work under this agreement, disclaim all",
2673
+    "liability to you for damages, costs and expenses, including legal",
2674
+    "fees.  YOU AGREE THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT",
2675
+    "LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE",
2676
+    "PROVIDED IN PARAGRAPH F3.  YOU AGREE THAT THE FOUNDATION, THE",
2677
+    "TRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE",
2678
+    "LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE OR",
2679
+    "INCIDENTAL DAMAGES EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH",
2680
+    "DAMAGE.",
2681
+    "1.F.3.  LIMITED RIGHT OF REPLACEMENT OR REFUND - If you discover a",
2682
+    "defect in this electronic work within 90 days of receiving it, you can",
2683
+    "receive a refund of the money (if any) you paid for it by sending a",
2684
+    "written explanation to the person you received the work from.  If you",
2685
+    "received the work on a physical medium, you must return the medium with",
2686
+    "your written explanation.  The person or entity that provided you with",
2687
+    "the defective work may elect to provide a replacement copy in lieu of a",
2688
+    "refund.  If you received the work electronically, the person or entity",
2689
+    "providing it to you may choose to give you a second opportunity to",
2690
+    "receive the work electronically in lieu of a refund.  If the second copy",
2691
+    "is also defective, you may demand a refund in writing without further",
2692
+    "opportunities to fix the problem.",
2693
+    "1.F.4.  Except for the limited right of replacement or refund set forth",
2694
+    "in paragraph 1.F.3, this work is provided to you ‘AS-IS’ WITH NO OTHER",
2695
+    "WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO",
2696
+    "WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR ANY PURPOSE.",
2697
+    "1.F.5.  Some states do not allow disclaimers of certain implied",
2698
+    "warranties or the exclusion or limitation of certain types of damages.",
2699
+    "If any disclaimer or limitation set forth in this agreement violates the",
2700
+    "law of the state applicable to this agreement, the agreement shall be",
2701
+    "interpreted to make the maximum disclaimer or limitation permitted by",
2702
+    "the applicable state law.  The invalidity or unenforceability of any",
2703
+    "provision of this agreement shall not void the remaining provisions.",
2704
+    "1.F.6.  INDEMNITY - You agree to indemnify and hold the Foundation, the",
2705
+    "trademark owner, any agent or employee of the Foundation, anyone",
2706
+    "providing copies of Project Gutenberg-tm electronic works in accordance",
2707
+    "with this agreement, and any volunteers associated with the production,",
2708
+    "promotion and distribution of Project Gutenberg-tm electronic works,",
2709
+    "harmless from all liability, costs and expenses, including legal fees,",
2710
+    "that arise directly or indirectly from any of the following which you do",
2711
+    "or cause to occur: (a) distribution of this or any Project Gutenberg-tm",
2712
+    "work, (b) alteration, modification, or additions or deletions to any",
2713
+    "Project Gutenberg-tm work, and (c) any Defect you cause.",
2714
+    "Section  2.  Information about the Mission of Project Gutenberg-tm",
2715
+    "Project Gutenberg-tm is synonymous with the free distribution of",
2716
+    "electronic works in formats readable by the widest variety of computers",
2717
+    "including obsolete, old, middle-aged and new computers.  It exists",
2718
+    "because of the efforts of hundreds of volunteers and donations from",
2719
+    "people in all walks of life.",
2720
+    "Volunteers and financial support to provide volunteers with the",
2721
+    "assistance they need, is critical to reaching Project Gutenberg-tm’s",
2722
+    "goals and ensuring that the Project Gutenberg-tm collection will",
2723
+    "remain freely available for generations to come.  In 2001, the Project",
2724
+    "Gutenberg Literary Archive Foundation was created to provide a secure",
2725
+    "and permanent future for Project Gutenberg-tm and future generations.",
2726
+    "To learn more about the Project Gutenberg Literary Archive Foundation",
2727
+    "and how your efforts and donations can help, see Sections 3 and 4",
2728
+    "and the Foundation web page at http://www.pglaf.org.",
2729
+    "Section 3.  Information about the Project Gutenberg Literary Archive",
2730
+    "Foundation",
2731
+    "The Project Gutenberg Literary Archive Foundation is a non profit",
2732
+    "501(c)(3) educational corporation organized under the laws of the",
2733
+    "state of Mississippi and granted tax exempt status by the Internal",
2734
+    "Revenue Service.  The Foundation’s EIN or federal tax identification",
2735
+    "number is 64-6221541.  Its 501(c)(3) letter is posted at",
2736
+    "http://pglaf.org/fundraising.  Contributions to the Project Gutenberg",
2737
+    "Literary Archive Foundation are tax deductible to the full extent",
2738
+    "permitted by U.S. federal laws and your state’s laws.",
2739
+    "The Foundation’s principal office is located at 4557 Melan Dr. S.",
2740
+    "Fairbanks, AK, 99712., but its volunteers and employees are scattered",
2741
+    "throughout numerous locations.  Its business office is located at",
2742
+    "809 North 1500 West, Salt Lake City, UT 84116, (801) 596-1887, email",
2743
+    "business@pglaf.org.  Email contact links and up to date contact",
2744
+    "information can be found at the Foundation’s web site and official",
2745
+    "page at http://pglaf.org",
2746
+    "For additional contact information:",
2747
+    "     Dr. Gregory B. Newby",
2748
+    "     Chief Executive and Director",
2749
+    "     gbnewby@pglaf.org",
2750
+    "Section 4.  Information about Donations to the Project Gutenberg",
2751
+    "Literary Archive Foundation",
2752
+    "Project Gutenberg-tm depends upon and cannot survive without wide",
2753
+    "spread public support and donations to carry out its mission of",
2754
+    "increasing the number of public domain and licensed works that can be",
2755
+    "freely distributed in machine readable form accessible by the widest",
2756
+    "array of equipment including outdated equipment.  Many small donations",
2757
+    "($1 to $5,000) are particularly important to maintaining tax exempt",
2758
+    "status with the IRS.",
2759
+    "The Foundation is committed to complying with the laws regulating",
2760
+    "charities and charitable donations in all 50 states of the United",
2761
+    "States.  Compliance requirements are not uniform and it takes a",
2762
+    "considerable effort, much paperwork and many fees to meet and keep up",
2763
+    "with these requirements.  We do not solicit donations in locations",
2764
+    "where we have not received written confirmation of compliance.  To",
2765
+    "SEND DONATIONS or determine the status of compliance for any",
2766
+    "particular state visit http://pglaf.org",
2767
+    "While we cannot and do not solicit contributions from states where we",
2768
+    "have not met the solicitation requirements, we know of no prohibition",
2769
+    "against accepting unsolicited donations from donors in such states who",
2770
+    "approach us with offers to donate.",
2771
+    "International donations are gratefully accepted, but we cannot make",
2772
+    "any statements concerning tax treatment of donations received from",
2773
+    "outside the United States.  U.S. laws alone swamp our small staff.",
2774
+    "Please check the Project Gutenberg Web pages for current donation",
2775
+    "methods and addresses.  Donations are accepted in a number of other",
2776
+    "ways including checks, online payments and credit card donations.",
2777
+    "To donate, please visit: http://pglaf.org/donate",
2778
+    "Section 5.  General Information About Project Gutenberg-tm electronic",
2779
+    "works.",
2780
+    "Professor Michael S. Hart is the originator of the Project Gutenberg-tm",
2781
+    "concept of a library of electronic works that could be freely shared",
2782
+    "with anyone.  For thirty years, he produced and distributed Project",
2783
+    "Gutenberg-tm eBooks with only a loose network of volunteer support.",
2784
+    "Project Gutenberg-tm eBooks are often created from several printed",
2785
+    "editions, all of which are confirmed as Public Domain in the U.S.",
2786
+    "unless a copyright notice is included.  Thus, we do not necessarily",
2787
+    "keep eBooks in compliance with any particular paper edition.",
2788
+    "Most people start at our Web site which has the main PG search facility:",
2789
+    "     http://www.gutenberg.org",
2790
+    "This Web site includes information about Project Gutenberg-tm,",
2791
+    "including how to make donations to the Project Gutenberg Literary",
2792
+    "Archive Foundation, how to help produce our new eBooks, and how to",
2793
+    "subscribe to our email newsletter to hear about new eBooks.",
2794
+    ""
2795
+};
2796
obs-studio-0.17.0.tar.xz/deps/libcaption/format.sh Added
5
 
1
@@ -0,0 +1,3 @@
2
+#!/bin/bash
3
+cd "$(dirname "$0")"
4
+find . \( -name '*.cpp' -o -name '*.c' -o -name '*.h' -o -name '*.hpp' -o -name '*.re2c' \) -exec astyle --style=stroustrup --attach-extern-c --break-blocks --pad-header --pad-paren-out --unpad-paren --add-brackets --keep-one-line-blocks --keep-one-line-statements --convert-tabs --align-pointer=type --align-reference=type --suffix=none --lineend=linux --max-code-length=180 {} \;
5
obs-studio-0.17.0.tar.xz/deps/libcaption/src Added
2
 
1
+(directory)
2
obs-studio-0.17.0.tar.xz/deps/libcaption/src/avc.c Added
597
 
1
@@ -0,0 +1,595 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+
26
+#include "avc.h"
27
+#include <stdlib.h>
28
+#include <string.h>
29
+#include <stdio.h>
30
+#include <assert.h>
31
+////////////////////////////////////////////////////////////////////////////////
32
+// AVC RBSP Methods
33
+//  TODO move the to a avcutils file
34
+static size_t _find_emulation_prevention_byte (const uint8_t* data, size_t size)
35
+{
36
+    size_t offset = 2;
37
+
38
+    while (offset < size) {
39
+        if (0 == data[offset]) {
40
+            // 0 0 X 3 //; we know X is zero
41
+            offset += 1;
42
+        } else if (3 != data[offset]) {
43
+            // 0 0 X 0 0 3; we know X is not 0 and not 3
44
+            offset += 3;
45
+        } else if (0 != data[offset-1]) {
46
+            // 0 X 0 0 3
47
+            offset += 2;
48
+        } else if (0 != data[offset-2]) {
49
+            // X 0 0 3
50
+            offset += 1;
51
+        } else {
52
+            // 0 0 3
53
+            return offset;
54
+        }
55
+    }
56
+
57
+    return size;
58
+}
59
+
60
+static size_t _copy_to_rbsp (uint8_t* destData, size_t destSize, const uint8_t* sorcData, size_t sorcSize)
61
+{
62
+    size_t toCopy, totlSize = 0;
63
+
64
+    for (;;) {
65
+        if (destSize >= sorcSize) {
66
+            return 0;
67
+        }
68
+
69
+        // The following line IS correct! We want to look in sorcData up to destSize bytes
70
+        // We know destSize is smaller than sorcSize because of the previous line
71
+        toCopy = _find_emulation_prevention_byte (sorcData,destSize);
72
+        memcpy (destData, sorcData, toCopy);
73
+        totlSize += toCopy;
74
+        destData += toCopy;
75
+        destSize -= toCopy;
76
+
77
+        if (0 == destSize) {
78
+            return totlSize;
79
+        }
80
+
81
+        // skip the emulation prevention byte
82
+        totlSize += 1;
83
+        sorcData += toCopy + 1;
84
+        sorcSize -= toCopy + 1;
85
+    }
86
+
87
+    return 0;
88
+}
89
+////////////////////////////////////////////////////////////////////////////////
90
+static inline size_t _find_emulated (uint8_t* data, size_t size)
91
+{
92
+    size_t offset = 2;
93
+
94
+    while (offset < size) {
95
+        if (3 < data[offset]) {
96
+            // 0 0 X; we know X is not 0, 1, 2 or 3
97
+            offset += 3;
98
+        } else if (0 != data[offset-1]) {
99
+            // 0 X 0 0 1
100
+            offset += 2;
101
+        } else if (0 != data[offset-2]) {
102
+            // X 0 0 1
103
+            offset += 1;
104
+        } else {
105
+            // 0 0 0, 0 0 1
106
+            return offset;
107
+        }
108
+    }
109
+
110
+    return size;
111
+}
112
+
113
+size_t _copy_from_rbsp (uint8_t* data, uint8_t* payloadData, size_t payloadSize)
114
+{
115
+    size_t total = 0;
116
+
117
+    while (payloadSize) {
118
+        size_t bytes = _find_emulated (payloadData,payloadSize);
119
+
120
+        if (bytes > payloadSize) {
121
+            return 0;
122
+        }
123
+
124
+        memcpy (data, payloadData, bytes);
125
+
126
+        if (bytes == payloadSize) {
127
+            return total + bytes;
128
+        }
129
+
130
+        data[bytes] = 3; // insert emulation prevention byte
131
+        data += bytes + 1; total += bytes + 1;
132
+        payloadData += bytes; payloadSize -= bytes;
133
+    }
134
+
135
+    return total;
136
+}
137
+////////////////////////////////////////////////////////////////////////////////
138
+struct _sei_message_t {
139
+    size_t size;
140
+    sei_msgtype_t type;
141
+    struct _sei_message_t* next;
142
+};
143
+
144
+sei_message_t* sei_message_next (sei_message_t* msg) { return ( (struct _sei_message_t*) msg)->next; }
145
+sei_msgtype_t  sei_message_type (sei_message_t* msg) { return ( (struct _sei_message_t*) msg)->type; }
146
+size_t         sei_message_size (sei_message_t* msg) { return ( (struct _sei_message_t*) msg)->size; }
147
+uint8_t*       sei_message_data (sei_message_t* msg) { return ( (uint8_t*) msg) + sizeof (struct _sei_message_t); }
148
+void           sei_message_free (sei_message_t* msg) { if (msg) { free (msg); } }
149
+
150
+sei_message_t* sei_message_new (sei_msgtype_t type, uint8_t* data, size_t size)
151
+{
152
+    struct _sei_message_t* msg = (struct _sei_message_t*) malloc (sizeof (struct _sei_message_t) + size);
153
+    msg->next = 0; msg->type = type; msg->size = size;
154
+
155
+    if (data) {
156
+        memcpy (sei_message_data (msg), data, size);
157
+    } else {
158
+        memset (sei_message_data (msg), 0, size);
159
+    }
160
+
161
+    return (sei_message_t*) msg;
162
+}
163
+////////////////////////////////////////////////////////////////////////////////
164
+void sei_init (sei_t* sei)
165
+{
166
+    sei->dts = -1;
167
+    sei->cts = -1;
168
+    sei->head = 0;
169
+    sei->tail = 0;
170
+}
171
+
172
+void sei_message_append (sei_t* sei, sei_message_t* msg)
173
+{
174
+    if (0 == sei->head) {
175
+        sei->head = msg;
176
+        sei->tail = msg;
177
+    } else {
178
+        sei->tail->next = msg;
179
+        sei->tail = msg;
180
+    }
181
+}
182
+
183
+void sei_free (sei_t* sei)
184
+{
185
+    sei_message_t* tail;
186
+
187
+    while (sei->head) {
188
+        tail = sei->head->next;
189
+        free (sei->head);
190
+        sei->head = tail;
191
+    }
192
+
193
+    sei_init (sei);
194
+}
195
+
196
+void sei_dump (sei_t* sei)
197
+{
198
+    fprintf (stderr,"SEI %p\n", sei);
199
+    sei_dump_messages (sei->head);
200
+}
201
+
202
+void sei_dump_messages (sei_message_t* head)
203
+{
204
+    cea708_t cea708;
205
+    sei_message_t* msg;
206
+    cea708_init (&cea708);
207
+
208
+    for (msg = head ; msg ; msg = sei_message_next (msg)) {
209
+        uint8_t* data = sei_message_data (msg);
210
+        size_t size =  sei_message_size (msg);
211
+        fprintf (stderr,"-- Message %p\n-- Message Type: %d\n-- Message Size: %d\n", data, sei_message_type (msg), (int) size);
212
+
213
+        while (size) {
214
+            fprintf (stderr,"%02X ", *data);
215
+            ++data; --size;
216
+        }
217
+
218
+        fprintf (stderr,"\n");
219
+
220
+        if (sei_type_user_data_registered_itu_t_t35 == sei_message_type (msg)) {
221
+            cea708_parse (sei_message_data (msg), sei_message_size (msg), &cea708);
222
+            cea708_dump (&cea708);
223
+        }
224
+
225
+
226
+    }
227
+}
228
+
229
+////////////////////////////////////////////////////////////////////////////////
230
+size_t sei_render_size (sei_t* sei)
231
+{
232
+    size_t size = 2; // nalu_type + stop bit
233
+    sei_message_t* msg;
234
+
235
+    for (msg = sei_message_head (sei) ; msg ; msg = sei_message_next (msg)) {
236
+        size += 1 + (msg->type / 255);
237
+        size += 1 + (msg->size / 255);
238
+        size += 1 + (msg->size * 4/3);
239
+    }
240
+
241
+    return size;
242
+}
243
+
244
+// we can safely assume sei_render_size() bytes have been allocated for data
245
+size_t sei_render (sei_t* sei, uint8_t* data)
246
+{
247
+    size_t escaped_size, size = 2; // nalu_type + stop bit
248
+    sei_message_t* msg;
249
+    (*data) = 6; ++data;
250
+
251
+    for (msg = sei_message_head (sei) ; msg ; msg = sei_message_next (msg)) {
252
+        int payloadType      = sei_message_type (msg);
253
+        int payloadSize      = (int) sei_message_size (msg);
254
+        uint8_t* payloadData = sei_message_data (msg);
255
+
256
+        while (255 <= payloadType) {
257
+            (*data) = 255;
258
+            ++data; ++size;
259
+            payloadType -= 255;
260
+        }
261
+
262
+        (*data) = payloadType;
263
+        ++data; ++size;
264
+
265
+        while (255 <= payloadSize) {
266
+            (*data) = 255;
267
+            ++data; ++size;
268
+            payloadSize -= 255;
269
+        }
270
+
271
+        (*data) = payloadSize;
272
+        ++data; ++size;
273
+
274
+        if (0 >= (escaped_size = _copy_from_rbsp (data,payloadData,payloadSize))) {
275
+            return 0;
276
+        }
277
+
278
+        data += escaped_size;
279
+        size += escaped_size;
280
+    }
281
+
282
+    // write stop bit and return
283
+    (*data) = 0x80;
284
+    return size;
285
+}
286
+
287
+uint8_t* sei_render_alloc (sei_t* sei, size_t* size)
288
+{
289
+    size_t aloc = sei_render_size (sei);
290
+    uint8_t* data = malloc (aloc);
291
+    (*size) = sei_render (sei, data);
292
+    return data;
293
+}
294
+
295
+////////////////////////////////////////////////////////////////////////////////
296
+int sei_parse_nalu (sei_t* sei, const uint8_t* data, size_t size, double dts, double cts)
297
+{
298
+    assert (0<=cts); // cant present before decode
299
+    sei->dts = dts;
300
+    sei->cts = cts;
301
+    int ret = 0;
302
+
303
+    if (0 == data || 0 == size) {
304
+        return 0;
305
+    }
306
+
307
+    uint8_t nal_unit_type = (*data) & 0x1F;
308
+    ++data; --size;
309
+
310
+    if (6 != nal_unit_type) {
311
+        return 0;
312
+    }
313
+
314
+    // SEI may contain more than one payload
315
+    while (1<size) {
316
+        int payloadType = 0;
317
+        int payloadSize = 0;
318
+
319
+        while (0 < size && 255 == (*data)) {
320
+            payloadType += 255;
321
+            ++data; --size;
322
+        }
323
+
324
+        if (0 == size) {
325
+            goto error;
326
+        }
327
+
328
+        payloadType += (*data);
329
+        ++data; --size;
330
+
331
+        while (0 < size && 255 == (*data)) {
332
+            payloadSize += 255;
333
+            ++data; --size;
334
+        }
335
+
336
+        if (0 == size) {
337
+            goto error;
338
+        }
339
+
340
+        payloadSize += (*data);
341
+        ++data; --size;
342
+
343
+        if (payloadSize) {
344
+            sei_message_t* msg = sei_message_new ( (sei_msgtype_t) payloadType, 0, payloadSize);
345
+            uint8_t* payloadData = sei_message_data (msg);
346
+            size_t bytes = _copy_to_rbsp (payloadData, payloadSize, data, size);
347
+            sei_message_append (sei, msg);
348
+
349
+            if ( (int) bytes < payloadSize) {
350
+                goto error;
351
+            }
352
+
353
+            data += bytes; size -= bytes;
354
+            ++ret;
355
+        }
356
+    }
357
+
358
+    // There should be one trailing byte, 0x80. But really, we can just ignore that fact.
359
+    return ret;
360
+error:
361
+    sei_init (sei);
362
+    return 0;
363
+}
364
+////////////////////////////////////////////////////////////////////////////////
365
+libcaption_stauts_t sei_to_caption_frame (sei_t* sei, caption_frame_t* frame)
366
+{
367
+    cea708_t cea708;
368
+    sei_message_t* msg;
369
+    libcaption_stauts_t status = LIBCAPTION_OK;
370
+
371
+    cea708_init (&cea708);
372
+
373
+    for (msg = sei_message_head (sei) ; msg ; msg = sei_message_next (msg)) {
374
+        if (sei_type_user_data_registered_itu_t_t35 == sei_message_type (msg)) {
375
+            cea708_parse (sei_message_data (msg), sei_message_size (msg), &cea708);
376
+            status = libcaption_status_update (status, cea708_to_caption_frame (frame, &cea708, sei_pts (sei)));
377
+        }
378
+    }
379
+
380
+    if (LIBCAPTION_READY == status) {
381
+        frame->timestamp = sei->dts + sei->cts;
382
+        frame->duration = 0;
383
+    }
384
+
385
+    return status;
386
+}
387
+
388
+////////////////////////////////////////////////////////////////////////////////
389
+#define DEFAULT_CHANNEL 0
390
+
391
+void sei_append_708 (sei_t* sei, cea708_t* cea708)
392
+{
393
+    sei_message_t* msg = sei_message_new (sei_type_user_data_registered_itu_t_t35, 0, CEA608_MAX_SIZE);
394
+    msg->size = cea708_render (cea708, sei_message_data (msg), sei_message_size (msg));
395
+    sei_message_append (sei,msg);
396
+    // cea708_dump (cea708);
397
+    cea708_init (cea708); // will confgure using HLS compatiable defaults
398
+}
399
+
400
+// This should be moved to 708.c
401
+// This works for popon, but bad for paint on and roll up
402
+// Please understand this function before you try to use it, setting null values have different effects than you may assume
403
+void sei_encode_eia608 (sei_t* sei, cea708_t* cea708, uint16_t cc_data)
404
+{
405
+    // This one is full, flush and init a new one
406
+    // shoudl this be 32? I cant remember
407
+    if (31 == cea708->user_data.cc_count) {
408
+        sei_append_708 (sei,cea708);
409
+    }
410
+
411
+    if (0 == cea708->user_data.cc_count) { // This is a new 708 header, but a continuation of a 608 stream
412
+        cea708_add_cc_data (cea708, 1, cc_type_ntsc_cc_field_1, eia608_control_command (eia608_control_resume_caption_loading, DEFAULT_CHANNEL));
413
+    }
414
+
415
+    if (0 == cc_data) { // Finished
416
+        sei_encode_eia608 (sei,cea708,eia608_control_command (eia608_control_end_of_caption, DEFAULT_CHANNEL));
417
+        sei_append_708 (sei,cea708);
418
+        return;
419
+    }
420
+
421
+    cea708_add_cc_data (cea708, 1, cc_type_ntsc_cc_field_1, cc_data);
422
+}
423
+////////////////////////////////////////////////////////////////////////////////
424
+// TODO use alternate charcters instead of always using space before extended charcters
425
+// TODO rewrite this function with better logic
426
+int sei_from_caption_frame (sei_t* sei, caption_frame_t* frame)
427
+{
428
+    int r,c;
429
+    cea708_t cea708;
430
+    const char* data;
431
+    uint16_t prev_cc_data;
432
+
433
+    cea708_init (&cea708); // set up a new popon frame
434
+    cea708_add_cc_data (&cea708, 1, cc_type_ntsc_cc_field_1, eia608_control_command (eia608_control_erase_non_displayed_memory, DEFAULT_CHANNEL));
435
+    cea708_add_cc_data (&cea708, 1, cc_type_ntsc_cc_field_1, eia608_control_command (eia608_control_resume_caption_loading, DEFAULT_CHANNEL));
436
+
437
+    for (r=0; r<SCREEN_ROWS; ++r) {
438
+        // Calculate preamble
439
+        for (c=0; c<SCREEN_COLS && 0 == *caption_frame_read_char (frame,r,c,0,0) ; ++c) {}
440
+
441
+        // This row is blank
442
+        if (SCREEN_COLS == c) {
443
+            continue;
444
+        }
445
+
446
+        // Write preamble
447
+        sei_encode_eia608 (sei, &cea708, eia608_row_column_pramble (r,c,DEFAULT_CHANNEL,0));
448
+        int tab = c % 4;
449
+
450
+        if (tab) {
451
+            sei_encode_eia608 (sei, &cea708, eia608_tab (tab,DEFAULT_CHANNEL));
452
+        }
453
+
454
+        // Write the row
455
+        for (prev_cc_data = 0, data = caption_frame_read_char (frame,r,c,0,0) ;
456
+                (*data) && c < SCREEN_COLS ; ++c, data = caption_frame_read_char (frame,r,c,0,0)) {
457
+            uint16_t cc_data = eia608_from_utf8_1 (data,DEFAULT_CHANNEL);
458
+
459
+            if (!cc_data) {
460
+                // We do't want to write bad data, so just ignore it.
461
+            } else if (eia608_is_basicna (prev_cc_data)) {
462
+                if (eia608_is_basicna (cc_data)) {
463
+                    // previous and current chars are both basicna, combine them into current
464
+                    sei_encode_eia608 (sei, &cea708, eia608_from_basicna (prev_cc_data,cc_data));
465
+                } else if (eia608_is_westeu (cc_data)) {
466
+                    // extended charcters overwrite the previous charcter, so insert a dummy char thren write the extended char
467
+                    sei_encode_eia608 (sei, &cea708, eia608_from_basicna (prev_cc_data,eia608_from_utf8_1 (EIA608_CHAR_SPACE,DEFAULT_CHANNEL)));
468
+                    sei_encode_eia608 (sei, &cea708, cc_data);
469
+                } else {
470
+                    // previous was basic na, but current isnt; write previous and current
471
+                    sei_encode_eia608 (sei, &cea708, prev_cc_data);
472
+                    sei_encode_eia608 (sei, &cea708, cc_data);
473
+                }
474
+
475
+                prev_cc_data = 0; // previous is handled, we can forget it now
476
+            } else if (eia608_is_westeu (cc_data)) {
477
+                // extended chars overwrite the previous chars, so insert a dummy char
478
+                sei_encode_eia608 (sei, &cea708, eia608_from_utf8_1 (EIA608_CHAR_SPACE,DEFAULT_CHANNEL));
479
+                sei_encode_eia608 (sei, &cea708, cc_data);
480
+            } else if (eia608_is_basicna (cc_data)) {
481
+                prev_cc_data = cc_data;
482
+            } else {
483
+                sei_encode_eia608 (sei, &cea708, cc_data);
484
+            }
485
+
486
+            if (eia608_is_specialna (cc_data)) {
487
+                // specialna are treated as controll charcters. Duplicated controll charcters are discarded
488
+                // So we for a resume after a specialna as a noop to break repetition detection
489
+                // TODO only do this if the same charcter is repeated
490
+                sei_encode_eia608 (sei, &cea708, eia608_control_command (eia608_control_resume_caption_loading, DEFAULT_CHANNEL));
491
+            }
492
+        }
493
+
494
+        if (0 != prev_cc_data) {
495
+            sei_encode_eia608 (sei, &cea708, prev_cc_data);
496
+        }
497
+    }
498
+
499
+    sei_encode_eia608 (sei, &cea708, 0); // flush
500
+    sei->dts = frame->timestamp; // assumes in order frames
501
+    // sei_dump (sei);
502
+    return 1;
503
+}
504
+////////////////////////////////////////////////////////////////////////////////
505
+static int avc_is_start_code (const uint8_t* data, int size, int* len)
506
+{
507
+    if (3 > size) {
508
+        return -1;
509
+    }
510
+
511
+    if (1 < data[2]) {
512
+        return 3;
513
+    }
514
+
515
+    if (0 != data[1]) {
516
+        return 2;
517
+    }
518
+
519
+    if (0 == data[0]) {
520
+        if (1 == data[2]) {
521
+            *len = 3;
522
+            return 0;
523
+        }
524
+
525
+        if (4 <= size && 1 == data[3]) {
526
+            *len = 4;
527
+            return 0;
528
+        }
529
+    }
530
+
531
+    return 1;
532
+}
533
+
534
+
535
+static int avc_find_start_code (const uint8_t* data, int size, int* len)
536
+{
537
+    int pos = 0;
538
+
539
+    for (;;) {
540
+        // is pos pointing to a start code?
541
+        int isc = avc_is_start_code (data + pos, size - pos, len);
542
+
543
+        if (0 < isc) {
544
+            pos += isc;
545
+        } else if (0 > isc) {
546
+            // No start code found
547
+            return isc;
548
+        } else {
549
+            // Start code found at pos
550
+            return pos;
551
+        }
552
+    }
553
+}
554
+
555
+
556
+static int avc_find_start_code_increnental (const uint8_t* data, int size, int prev_size, int* len)
557
+{
558
+    int offset = (3 <= prev_size) ? (prev_size - 3) : 0;
559
+    int pos = avc_find_start_code (data + offset, size - offset, len);
560
+
561
+    if (0 <= pos) {
562
+        return pos + offset;
563
+    }
564
+
565
+    return pos;
566
+}
567
+
568
+void avcnalu_init (avcnalu_t* nalu)
569
+{
570
+    memset (nalu,0,sizeof (avcnalu_t));
571
+}
572
+
573
+int avcnalu_parse_annexb (avcnalu_t* nalu, const uint8_t** data, size_t* size)
574
+{
575
+    int scpos, sclen;
576
+    int new_size = (int) (nalu->size + (*size));
577
+
578
+    if (new_size > MAX_NALU_SIZE) {
579
+        (*size) = nalu->size = 0;
580
+        return LIBCAPTION_ERROR;
581
+    }
582
+
583
+    memcpy (&nalu->data[nalu->size], (*data), (*size));
584
+    scpos = avc_find_start_code_increnental (&nalu->data[0], new_size, (int) nalu->size, &sclen);
585
+
586
+    if (0<=scpos) {
587
+        (*data) += (scpos - nalu->size) + sclen;
588
+        (*size) -= (scpos - nalu->size) + sclen;
589
+        nalu->size = scpos;
590
+        return 0 < nalu->size ? LIBCAPTION_READY : LIBCAPTION_OK;
591
+    } else {
592
+        (*size) = 0;
593
+        nalu->size = new_size;
594
+        return LIBCAPTION_OK;
595
+    }
596
+}
597
obs-studio-0.17.0.tar.xz/deps/libcaption/src/caption.c Added
493
 
1
@@ -0,0 +1,491 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#include "utf8.h"
26
+#include "xds.h"
27
+#include "eia608.h"
28
+#include "caption.h"
29
+#include <stdio.h>
30
+#include <string.h>
31
+////////////////////////////////////////////////////////////////////////////////
32
+void caption_frame_buffer_clear (caption_frame_buffer_t* buff)
33
+{
34
+    memset (buff,0,sizeof (caption_frame_buffer_t));
35
+}
36
+
37
+void caption_frame_state_clear (caption_frame_t* frame)
38
+{
39
+    frame->timestamp = -1;
40
+    frame->duration = 0;
41
+    frame->state = (caption_frame_state_t) {0,0,0,0,0,0,0}; // clear global state
42
+}
43
+
44
+void caption_frame_init (caption_frame_t* frame)
45
+{
46
+    caption_frame_state_clear (frame);
47
+    xds_init (&frame->xds);
48
+    caption_frame_buffer_clear (&frame->back);
49
+    caption_frame_buffer_clear (&frame->front);
50
+}
51
+////////////////////////////////////////////////////////////////////////////////
52
+#define CAPTION_CLEAR     0
53
+#define CAPTION_POP_ON    2
54
+#define CAPTION_PAINT_ON  3
55
+#define CAPTION_ROLL_UP   4
56
+////////////////////////////////////////////////////////////////////////////////
57
+// Helpers
58
+static caption_frame_cell_t* frame_buffer_cell (caption_frame_buffer_t* buff, int row, int col)
59
+{
60
+    return &buff->cell[row][col];
61
+}
62
+
63
+static caption_frame_buffer_t* frame_write_buffer (caption_frame_t* frame)
64
+{
65
+    if (CAPTION_POP_ON == frame->state.mod) {
66
+        return &frame->back;
67
+    } else if (CAPTION_PAINT_ON == frame->state.mod || CAPTION_ROLL_UP == frame->state.mod) {
68
+        return &frame->front;
69
+    } else {
70
+        return 0;
71
+    }
72
+}
73
+
74
+static caption_frame_cell_t* frame_cell (caption_frame_t* frame, int row, int col)
75
+{
76
+    return frame_buffer_cell (&frame->front,row,col);
77
+}
78
+
79
+static caption_frame_cell_t* frame_cell_get (caption_frame_t* frame)
80
+{
81
+    return frame_cell (frame, frame->state.row, frame->state.col);
82
+}
83
+
84
+////////////////////////////////////////////////////////////////////////////////
85
+uint16_t _eia608_from_utf8 (const char* s); // function is in eia608.c.re2c
86
+int caption_frame_write_char (caption_frame_t* frame, int row, int col, eia608_style_t style, int underline, const char* c)
87
+{
88
+    caption_frame_buffer_t* buff = frame_write_buffer (frame);
89
+
90
+    if (!buff || ! _eia608_from_utf8 (c)) {
91
+        return 0;
92
+    }
93
+
94
+    caption_frame_cell_t* cell = frame_buffer_cell (buff,row,col);
95
+
96
+    if (utf8_char_copy (&cell->data[0],c)) {
97
+        cell->uln = underline;
98
+        cell->sty = style;
99
+        return 1;
100
+    }
101
+
102
+    return 0;
103
+}
104
+
105
+const utf8_char_t* caption_frame_read_char (caption_frame_t* frame, int row, int col, eia608_style_t* style, int* underline)
106
+{
107
+    caption_frame_cell_t* cell = frame_cell (frame, row, col);
108
+
109
+    if (!cell) {
110
+        if (style) {
111
+            (*style) = eia608_style_white;
112
+        }
113
+
114
+        if (underline) {
115
+            (*underline) = 0;
116
+        }
117
+
118
+        return EIA608_CHAR_NULL;
119
+    }
120
+
121
+    if (style) {
122
+        (*style) = cell->sty;
123
+    }
124
+
125
+    if (underline) {
126
+        (*underline) = cell->uln;
127
+    }
128
+
129
+    return &cell->data[0];
130
+}
131
+
132
+////////////////////////////////////////////////////////////////////////////////
133
+// Parsing
134
+libcaption_stauts_t caption_frame_carriage_return (caption_frame_t* frame)
135
+{
136
+    caption_frame_buffer_t* buff = frame_write_buffer (frame);
137
+
138
+    if (!buff) {
139
+        return LIBCAPTION_OK;
140
+    }
141
+
142
+    int r = frame->state.row - (frame->state.rup-1);
143
+
144
+    if (0  >= r || CAPTION_ROLL_UP != frame->state.mod) {
145
+        return LIBCAPTION_OK;
146
+    }
147
+
148
+    for (; r < SCREEN_ROWS; ++r) {
149
+        uint8_t* dst = (uint8_t*) frame_buffer_cell (buff,r-1,0);
150
+        uint8_t* src = (uint8_t*) frame_buffer_cell (buff,r-0,0);
151
+        memcpy (dst,src,sizeof (caption_frame_cell_t) * SCREEN_COLS);
152
+    }
153
+
154
+    memset (frame_buffer_cell (buff,SCREEN_ROWS-1,0), 0,sizeof (caption_frame_cell_t) * SCREEN_COLS);
155
+    return LIBCAPTION_OK;
156
+}
157
+////////////////////////////////////////////////////////////////////////////////
158
+libcaption_stauts_t eia608_write_char (caption_frame_t* frame, char* c)
159
+{
160
+    if (0 == c || 0 == c[0] ||
161
+            SCREEN_ROWS <= frame->state.row || 0 > frame->state.row ||
162
+            SCREEN_COLS <= frame->state.col || 0 > frame->state.col) {
163
+        // NO-OP
164
+    } else if (caption_frame_write_char (frame,frame->state.row,frame->state.col,frame->state.sty,frame->state.uln, c)) {
165
+        frame->state.col += 1;
166
+    }
167
+
168
+    return LIBCAPTION_OK;
169
+}
170
+
171
+libcaption_stauts_t caption_frame_end (caption_frame_t* frame)
172
+{
173
+    memcpy (&frame->front,&frame->back,sizeof (caption_frame_buffer_t));
174
+    caption_frame_state_clear (frame);
175
+    caption_frame_buffer_clear (&frame->back);
176
+    return LIBCAPTION_READY;
177
+}
178
+
179
+libcaption_stauts_t caption_frame_decode_preamble (caption_frame_t* frame, uint16_t cc_data)
180
+{
181
+    eia608_style_t sty;
182
+    int row, col, chn, uln;
183
+
184
+    if (eia608_parse_preamble (cc_data, &row, &col, &sty, &chn, &uln)) {
185
+        frame->state.row = row;
186
+        frame->state.col = col;
187
+        frame->state.sty = sty;
188
+        frame->state.uln = uln;
189
+    }
190
+
191
+    return LIBCAPTION_OK;
192
+}
193
+
194
+libcaption_stauts_t caption_frame_decode_midrowchange (caption_frame_t* frame, uint16_t cc_data)
195
+{
196
+    eia608_style_t sty;
197
+    int chn, unl;
198
+
199
+    if (eia608_parse_midrowchange (cc_data,&chn,&sty,&unl)) {
200
+        frame->state.sty = sty;
201
+        frame->state.uln = unl;
202
+    }
203
+
204
+    return LIBCAPTION_OK;
205
+}
206
+
207
+libcaption_stauts_t caption_frame_backspace (caption_frame_t* frame)
208
+{
209
+    // do not reverse wrap (tw 28:20)
210
+    frame->state.col = (0 < frame->state.col) ? (frame->state.col - 1) : 0;
211
+    caption_frame_write_char (frame,frame->state.row,frame->state.col,eia608_style_white,0,EIA608_CHAR_NULL);
212
+    return LIBCAPTION_READY;
213
+}
214
+
215
+libcaption_stauts_t caption_frame_decode_control (caption_frame_t* frame, uint16_t cc_data)
216
+{
217
+    int cc;
218
+    eia608_control_t cmd = eia608_parse_control (cc_data,&cc);
219
+
220
+    switch (cmd) {
221
+    // PAINT ON
222
+    case eia608_control_resume_direct_captioning:
223
+        frame->state.rup = 0;
224
+        frame->state.mod = CAPTION_PAINT_ON;
225
+        return LIBCAPTION_OK;
226
+
227
+    case eia608_control_erase_display_memory:
228
+        caption_frame_buffer_clear (&frame->front);
229
+        return LIBCAPTION_OK;
230
+
231
+    // ROLL-UP
232
+    case eia608_control_roll_up_2:
233
+        frame->state.rup = 1;
234
+        frame->state.mod = CAPTION_ROLL_UP;
235
+        return LIBCAPTION_OK;
236
+
237
+    case eia608_control_roll_up_3:
238
+        frame->state.rup = 2;
239
+        frame->state.mod = CAPTION_ROLL_UP;
240
+        return LIBCAPTION_OK;
241
+
242
+    case eia608_control_roll_up_4:
243
+        frame->state.rup = 3;
244
+        frame->state.mod = CAPTION_ROLL_UP;
245
+        return LIBCAPTION_OK;
246
+
247
+    case eia608_control_carriage_return:
248
+        return caption_frame_carriage_return (frame);
249
+
250
+    // Corrections (Is this only valid as part of paint on?)
251
+    case eia608_control_backspace:
252
+        return caption_frame_backspace (frame);
253
+
254
+    case eia608_control_delete_to_end_of_row: {
255
+        int c;
256
+
257
+        for (c = frame->state.col ; c < SCREEN_COLS ; ++c) {
258
+            caption_frame_write_char (frame,frame->state.row,c,eia608_style_white,0,EIA608_CHAR_NULL);
259
+        }
260
+    }
261
+
262
+    return LIBCAPTION_READY;
263
+
264
+    // POP ON
265
+    case eia608_control_resume_caption_loading:
266
+        frame->state.rup = 0;
267
+        frame->state.mod = CAPTION_POP_ON;
268
+        return LIBCAPTION_OK;
269
+
270
+    case eia608_control_erase_non_displayed_memory:
271
+        caption_frame_buffer_clear (&frame->back);
272
+        return LIBCAPTION_OK;
273
+
274
+    case eia608_control_end_of_caption:
275
+        return caption_frame_end (frame);
276
+
277
+    // cursor positioning
278
+    case eia608_tab_offset_0:
279
+    case eia608_tab_offset_1:
280
+    case eia608_tab_offset_2:
281
+    case eia608_tab_offset_3:
282
+        frame->state.col += (cmd - eia608_tab_offset_0);
283
+        return LIBCAPTION_OK;
284
+
285
+    // Unhandled
286
+    default:
287
+    case eia608_control_alarm_off:
288
+    case eia608_control_alarm_on:
289
+    case eia608_control_text_restart:
290
+    case eia608_control_text_resume_text_display:
291
+        return LIBCAPTION_OK;
292
+    }
293
+}
294
+
295
+libcaption_stauts_t caption_frame_decode_text (caption_frame_t* frame, uint16_t cc_data)
296
+{
297
+    int chan;
298
+    char char1[5], char2[5];
299
+    size_t chars = eia608_to_utf8 (cc_data, &chan, &char1[0], &char2[0]);
300
+
301
+    if (eia608_is_westeu (cc_data)) {
302
+        // Extended charcters replace the previous charcter for back compatibility
303
+        caption_frame_backspace (frame);
304
+    }
305
+
306
+    if (0 < chars) {
307
+        eia608_write_char (frame,char1);
308
+    }
309
+
310
+    if (1 < chars) {
311
+        eia608_write_char (frame,char2);
312
+    }
313
+
314
+    return LIBCAPTION_OK;
315
+}
316
+
317
+libcaption_stauts_t caption_frame_decode (caption_frame_t* frame, uint16_t cc_data, double timestamp)
318
+{
319
+    libcaption_stauts_t status = LIBCAPTION_OK;
320
+
321
+    if (!eia608_parity_varify (cc_data)) {
322
+        return LIBCAPTION_ERROR;
323
+    }
324
+
325
+    if (eia608_is_padding (cc_data)) {
326
+        return LIBCAPTION_OK;
327
+    }
328
+
329
+    // skip duplicate controll commands. We also skip duplicate specialna to match the behaviour of iOS/vlc
330
+    if ( (eia608_is_specialna (cc_data) || eia608_is_control (cc_data)) && cc_data == frame->state.cc_data) {
331
+        return LIBCAPTION_OK;
332
+    }
333
+
334
+    if (0 > frame->timestamp && 0 < timestamp) {
335
+        frame->timestamp = timestamp;
336
+    }
337
+
338
+    frame->state.cc_data = cc_data;
339
+
340
+    if (frame->xds.state) {
341
+        status = xds_decode (&frame->xds,cc_data);
342
+    } else if (eia608_is_xds (cc_data)) {
343
+        status = xds_decode (&frame->xds,cc_data);
344
+    } else if (eia608_is_control (cc_data)) {
345
+        status = caption_frame_decode_control (frame,cc_data);
346
+    } else if (eia608_is_basicna (cc_data) ||
347
+               eia608_is_specialna (cc_data) ||
348
+               eia608_is_westeu (cc_data)) {
349
+
350
+        // Don't decode text if we dont know what mode we are in.
351
+        if (CAPTION_CLEAR == frame->state.mod) {
352
+            return LIBCAPTION_OK;
353
+        }
354
+
355
+        status = caption_frame_decode_text (frame,cc_data);
356
+
357
+        // If we are in paint on mode, display immiditally
358
+        if (1 == status && (CAPTION_PAINT_ON == frame->state.mod || CAPTION_ROLL_UP == frame->state.mod)) {
359
+            status = LIBCAPTION_READY;
360
+        }
361
+    } else if (eia608_is_preamble (cc_data)) {
362
+        status = caption_frame_decode_preamble (frame,cc_data);
363
+    } else if (eia608_is_midrowchange (cc_data)) {
364
+        status = caption_frame_decode_midrowchange (frame,cc_data);
365
+    }
366
+
367
+    return status;
368
+}
369
+
370
+////////////////////////////////////////////////////////////////////////////////
371
+int caption_frame_from_text (caption_frame_t* frame, const utf8_char_t* data)
372
+{
373
+    int r, c, chan = 0;
374
+    ssize_t size = (ssize_t) strlen (data);
375
+    size_t char_count, char_length, line_length = 0, trimmed_length = 0;
376
+    caption_frame_init (frame);
377
+    frame->state.mod = CAPTION_POP_ON;
378
+
379
+    for (r = 0 ; 0 < size && SCREEN_ROWS > r ; ++r) {
380
+        const utf8_char_t* cap_data = data;
381
+        line_length = utf8_line_length (cap_data);
382
+        trimmed_length = utf8_trimmed_length (cap_data,line_length);
383
+        char_count = utf8_char_count (cap_data,trimmed_length);
384
+
385
+        // If char_count is greater than one line can display, split it.
386
+        if (SCREEN_COLS < char_count) {
387
+            char_count = utf8_wrap_length (cap_data,SCREEN_COLS);
388
+            line_length = utf8_string_length (cap_data,char_count+1);
389
+        }
390
+
391
+        // Write the line
392
+        for (c = 0 ; c < (int) char_count ; ++c) {
393
+            caption_frame_write_char (frame,r,c,eia608_style_white,0,&cap_data[0]);
394
+            char_length = utf8_char_length (cap_data);
395
+            cap_data += char_length;
396
+        }
397
+
398
+        data += line_length;
399
+        size -= (ssize_t) line_length;
400
+    }
401
+
402
+    caption_frame_end (frame);
403
+    return 0;
404
+}
405
+////////////////////////////////////////////////////////////////////////////////
406
+void caption_frame_to_text (caption_frame_t* frame, utf8_char_t* data)
407
+{
408
+    int r, c, x, s, uln;
409
+    eia608_style_t sty;
410
+
411
+    data[0] = 0;
412
+
413
+    for (r = 0 ; r < SCREEN_ROWS ; ++r) {
414
+        for (c = 0, x = 0 ; c < SCREEN_COLS ; ++c) {
415
+            const char* chr  = caption_frame_read_char (frame, r, c, &sty, &uln);
416
+
417
+            if (0 < (s = (int) utf8_char_copy (data,chr))) {
418
+                ++x; data += s;
419
+            }
420
+        }
421
+
422
+        if (x) {
423
+            strcpy ( (char*) data,"\r\n");
424
+            data += 2;
425
+        }
426
+    }
427
+}
428
+////////////////////////////////////////////////////////////////////////////////
429
+size_t caption_frame_dump_buffer (caption_frame_t* frame, utf8_char_t* buf)
430
+{
431
+    int r, c;
432
+    size_t bytes, total = 0;
433
+    bytes = sprintf (buf, "   row: %d\tcol: %d\n   mode: %s\troll-up: %d\n",
434
+                     frame->state.row, frame->state.col,
435
+                     eia608_mode_map[frame->state.mod],frame->state.rup?1+frame->state.rup:0);
436
+    total += bytes; buf += bytes;
437
+    bytes = sprintf (buf, "   00000000001111111111222222222233\n   01234567890123456789012345678901\n  %s--------------------------------%s\n",
438
+                     EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_RIGHT, EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_LEFT);
439
+    total += bytes; buf += bytes;
440
+
441
+    for (r = 0 ; r < SCREEN_ROWS ; ++r) {
442
+        bytes = sprintf (buf, "%02d%s", r, EIA608_CHAR_VERTICAL_LINE);
443
+        total += bytes; buf += bytes;
444
+
445
+        for (c = 0 ; c < SCREEN_COLS ; ++c) {
446
+            caption_frame_cell_t* cell = frame_cell (frame,r,c);
447
+            bytes = utf8_char_copy (buf, (0==cell->data[0]) ?EIA608_CHAR_SPACE:&cell->data[0]);
448
+            total += bytes; buf += bytes;
449
+        }
450
+
451
+        bytes = sprintf (buf, "%s\n", EIA608_CHAR_VERTICAL_LINE);
452
+        total += bytes; buf += bytes;
453
+    }
454
+
455
+    bytes = sprintf (buf, "  %s--------------------------------%s\n",
456
+                     EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_RIGHT, EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_LEFT);
457
+    total += bytes; buf += bytes;
458
+    return total;
459
+}
460
+
461
+void caption_frame_dump (caption_frame_t* frame)
462
+{
463
+    utf8_char_t buff[CAPTION_FRAME_DUMP_BUF_SIZE];
464
+    size_t size = caption_frame_dump_buffer (frame, buff);
465
+    fprintf (stderr,"%s\n", buff);
466
+}
467
+
468
+size_t caption_frame_json (caption_frame_t* frame, utf8_char_t* buf)
469
+{
470
+    size_t bytes, total = 0;
471
+    int r,c,count = 0;
472
+    bytes = sprintf (buf, "{\"format\":\"eia608\",\"mode\":\"%s\",\"rollUp\":%d,\"data\":[",
473
+                     eia608_mode_map[frame->state.mod],frame->state.rup?1+frame->state.rup:0);
474
+    total += bytes; buf += bytes;
475
+
476
+    for (r = 0 ; r < SCREEN_ROWS ; ++r) {
477
+        for (c = 0 ; c < SCREEN_COLS ; ++c) {
478
+            caption_frame_cell_t* cell = frame_cell (frame,r,c);
479
+
480
+            if (0 != cell->data[0]) {
481
+                const char* data = ('"' == cell->data[0]) ?"\\\"": (const char*) &cell->data[0]; //escape quote
482
+                bytes = sprintf (buf, "%s\n{\"row\":%d,\"col\":%d,\"char\":\"%s\",\"style\":\"%s\"}",
483
+                                 (0<count?",":""),r,c,data,eia608_style_map[cell->sty]);
484
+                total += bytes; buf += bytes; ++count;
485
+            }
486
+        }
487
+    }
488
+
489
+    bytes = sprintf (buf, "\n]}\n");
490
+    total += bytes; buf += bytes;
491
+    return total;
492
+}
493
obs-studio-0.17.0.tar.xz/deps/libcaption/src/cea708.c Added
209
 
1
@@ -0,0 +1,207 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#include "cea708.h"
26
+#include <memory.h>
27
+
28
+int cea708_cc_count (user_data_t* data)
29
+{
30
+    return data->cc_count;
31
+}
32
+
33
+uint16_t cea708_cc_data (user_data_t* data, int index, int* valid, cea708_cc_type_t* type)
34
+{
35
+    (*valid) = data->cc_data[index].cc_valid;
36
+    (*type) = data->cc_data[index].cc_type;
37
+    return data->cc_data[index].cc_data;
38
+}
39
+
40
+
41
+int cea708_init (cea708_t* cea708)
42
+{
43
+    memset (cea708,0,sizeof (cea708_t));
44
+    cea708->country = country_united_states;
45
+    cea708->provider = t35_provider_atsc;
46
+    cea708->user_identifier = ('G'<<24) | ('A'<<16) | ('9'<<8) | ('4');
47
+    cea708->atsc1_data_user_data_type_code = 3; //what does 3 mean here?
48
+    cea708->directv_user_data_length = 0;
49
+    ///////////
50
+    cea708->user_data.process_em_data_flag = 0;
51
+    cea708->user_data.process_cc_data_flag = 1;
52
+    cea708->user_data.additional_data_flag = 0;
53
+    cea708->user_data.cc_count = 0;
54
+    return 1;
55
+}
56
+
57
+// 00 00 00  06 C1  FF FC 34 B9 FF : onCaptionInfo.
58
+int cea708_parse (uint8_t* data, size_t size, cea708_t* cea708)
59
+{
60
+    int i;
61
+    cea708->country = (itu_t_t35_country_code_t) (data[0]);
62
+    cea708->provider = (itu_t_t35_provider_code_t) ( (data[1] <<8) | data[2]);
63
+    cea708->atsc1_data_user_data_type_code = 0;
64
+    cea708->user_identifier = 0;
65
+    data += 3; size -= 3;
66
+
67
+    if (t35_provider_atsc == cea708->provider) {
68
+        // GA94
69
+        cea708->user_identifier = (data[0] <<24) | (data[1] <<16) | (data[2] <<8) | data[3];
70
+        data += 4; size -= 4;
71
+    }
72
+
73
+    // Im not sure what this extra byt is. It sonly seesm to come up in onCaptionInfo
74
+    // where country and provider are zero
75
+    if (0 == cea708->provider) {
76
+        data += 1; size -= 1;
77
+    } else if (t35_provider_atsc == cea708->provider || t35_provider_direct_tv == cea708->provider) {
78
+        cea708->atsc1_data_user_data_type_code = data[0];
79
+        data += 1; size -= 1;
80
+    }
81
+
82
+    if (t35_provider_direct_tv == cea708->provider) {
83
+        cea708->directv_user_data_length = data[0];
84
+        data += 1; size -= 1;
85
+    }
86
+
87
+    // TODO I believe this is condational on the above.
88
+    cea708->user_data.process_em_data_flag = !! (data[0]&0x80);
89
+    cea708->user_data.process_cc_data_flag = !! (data[0]&0x40);
90
+    cea708->user_data.additional_data_flag = !! (data[0]&0x20);
91
+    cea708->user_data.cc_count             = (data[0]&0x1F);
92
+    cea708->user_data.em_data              = data[1];
93
+    data += 2; size -= 2;
94
+
95
+    if (size < 3 * cea708->user_data.cc_count) {
96
+        cea708_init (cea708);
97
+        return 0;
98
+    }
99
+
100
+    for (i = 0 ; i < (int) cea708->user_data.cc_count ; ++i) {
101
+        cea708->user_data.cc_data[i].marker_bits = data[0]>>3;
102
+        cea708->user_data.cc_data[i].cc_valid    = data[0]>>2;
103
+        cea708->user_data.cc_data[i].cc_type     = data[0]>>0;
104
+        cea708->user_data.cc_data[i].cc_data     = data[1]<<8|data[2];
105
+        data += 3; size -= 3;
106
+    }
107
+
108
+    return 1;
109
+}
110
+
111
+int cea708_add_cc_data (cea708_t* cea708, int valid, cea708_cc_type_t type, uint16_t cc_data)
112
+{
113
+    if (31 <= cea708->user_data.cc_count) {
114
+        return 0;
115
+    }
116
+
117
+    cea708->user_data.cc_data[cea708->user_data.cc_count].marker_bits = 0x1F;
118
+    cea708->user_data.cc_data[cea708->user_data.cc_count].cc_valid = valid;
119
+    cea708->user_data.cc_data[cea708->user_data.cc_count].cc_type = type;
120
+    cea708->user_data.cc_data[cea708->user_data.cc_count].cc_data = cc_data;
121
+    ++cea708->user_data.cc_count;
122
+    return 1;
123
+}
124
+
125
+int cea708_render (cea708_t* cea708, uint8_t* data, size_t size)
126
+{
127
+    int i;    size_t total = 0;
128
+    data[0] = cea708->country;
129
+    data[1] = cea708->provider>>8;
130
+    data[2] = cea708->provider>>0;
131
+    total += 3; data += 3; size -= 3;
132
+
133
+    if (t35_provider_atsc == cea708->provider) {
134
+
135
+        data[0] = cea708->user_identifier >> 24;
136
+        data[1] = cea708->user_identifier >> 16;
137
+        data[2] = cea708->user_identifier >> 8;
138
+        data[3] = cea708->user_identifier >> 0;
139
+        total += 4; data += 4; size -= 4;
140
+    }
141
+
142
+    if (t35_provider_atsc == cea708->provider || t35_provider_direct_tv == cea708->provider) {
143
+        data[0] = cea708->atsc1_data_user_data_type_code;
144
+        total += 1; data += 1; size -= 1;
145
+    }
146
+
147
+    if (t35_provider_direct_tv == cea708->provider) {
148
+        data[0] = cea708->directv_user_data_length;
149
+        total += 1; data += 1; size -= 1;
150
+    }
151
+
152
+    data[1] = cea708->user_data.em_data;
153
+    data[0] = (cea708->user_data.process_em_data_flag?0x80:0x00)
154
+              | (cea708->user_data.process_cc_data_flag?0x40:0x00)
155
+              | (cea708->user_data.additional_data_flag?0x20:0x00)
156
+              | (cea708->user_data.cc_count & 0x1F);
157
+
158
+    total += 2; data += 2; size -= 2;
159
+
160
+    for (i = 0 ; i < (int) cea708->user_data.cc_count ; ++i) {
161
+        data[0] = (cea708->user_data.cc_data[i].marker_bits<<3)
162
+                  | (data[0] = cea708->user_data.cc_data[i].cc_valid<<2)
163
+                  | (data[0] = cea708->user_data.cc_data[i].cc_type);
164
+        data[1] = cea708->user_data.cc_data[i].cc_data>>8;
165
+        data[2] = cea708->user_data.cc_data[i].cc_data>>0;
166
+        total += 3; data += 3; size -= 3;
167
+    }
168
+
169
+    data[0] = 0xFF;
170
+    return (int) (total + 1);
171
+}
172
+
173
+cc_data_t cea708_encode_cc_data (int cc_valid, cea708_cc_type_t type, uint16_t cc_data)
174
+{
175
+    cc_data_t data = { 0x1F, cc_valid,type,cc_data};
176
+    return data;
177
+}
178
+
179
+void cea708_dump (cea708_t* cea708)
180
+{
181
+    int i;
182
+
183
+    for (i = 0 ; i < (int) cea708->user_data.cc_count ; ++i) {
184
+        cea708_cc_type_t type; int valid;
185
+        uint16_t cc_data = cea708_cc_data (&cea708->user_data, i, &valid, &type);
186
+
187
+        if (valid && cc_type_ntsc_cc_field_1 == type) {
188
+            eia608_dump (cc_data);
189
+        }
190
+    }
191
+}
192
+
193
+libcaption_stauts_t cea708_to_caption_frame (caption_frame_t* frame, cea708_t* cea708, double pts)
194
+{
195
+    int i, count = cea708_cc_count (&cea708->user_data);
196
+    libcaption_stauts_t status = LIBCAPTION_OK;
197
+
198
+    for (i = 0 ; i < count ; ++i) {
199
+        cea708_cc_type_t type; int valid;
200
+        uint16_t cc_data = cea708_cc_data (&cea708->user_data, i, &valid, &type);
201
+
202
+        if (valid && cc_type_ntsc_cc_field_1 == type) {
203
+            status = libcaption_status_update (status,caption_frame_decode (frame,cc_data, pts));
204
+        }
205
+    }
206
+
207
+    return status;
208
+}
209
obs-studio-0.17.0.tar.xz/deps/libcaption/src/eia608.c Added
756
 
1
@@ -0,0 +1,754 @@
2
+/* Generated by re2c 0.15.3 on Tue Nov 22 15:42:35 2016 */
3
+/**********************************************************************************************/
4
+/* The MIT License                                                                            */
5
+/*                                                                                            */
6
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
7
+/*                                                                                            */
8
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
9
+/* of this software and associated documentation files (the "Software"), to deal              */
10
+/* in the Software without restriction, including without limitation the rights               */
11
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
12
+/* copies of the Software, and to permit persons to whom the Software is                      */
13
+/* furnished to do so, subject to the following conditions:                                   */
14
+/*                                                                                            */
15
+/* The above copyright notice and this permission notice shall be included in                 */
16
+/* all copies or substantial portions of the Software.                                        */
17
+/*                                                                                            */
18
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
19
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
20
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
21
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
22
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
23
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
24
+/* THE SOFTWARE.                                                                              */
25
+/**********************************************************************************************/
26
+#include "eia608.h"
27
+#include <string.h>
28
+#include <stdio.h>
29
+
30
+////////////////////////////////////////////////////////////////////////////////
31
+int eia608_row_map[] = {10, -1, 0, 1, 2, 3, 11, 12, 13, 14, 4, 5, 6, 7, 8, 9};
32
+int eia608_reverse_row_map[] = {2, 3, 4, 5, 10, 11, 12, 13, 14, 15, 0, 6, 7, 8, 9, 1};
33
+
34
+const char* eia608_mode_map[] = {
35
+    "clear",
36
+    "loading",
37
+    "popOn",
38
+    "paintOn",
39
+    "rollUp",
40
+};
41
+
42
+const char* eia608_style_map[] = {
43
+    "white",
44
+    "green",
45
+    "blue",
46
+    "cyan",
47
+    "red",
48
+    "yellow",
49
+    "magenta",
50
+    "italics",
51
+};
52
+
53
+static inline uint16_t eia608_row_pramble (int row, int chan, int x, int underline)
54
+{
55
+    row = eia608_reverse_row_map[row&0x0F];
56
+    return eia608_parity (0x1040 | (chan?0x0800:0x0000) | ( (row<<7) &0x0700) | ( (row<<5) &0x0020)) | ( (x<<1) &0x001E) | (underline?0x0001:0x0000);
57
+}
58
+
59
+uint16_t eia608_row_column_pramble (int row, int col, int chan, int underline) { return eia608_row_pramble (row,chan,0x10| (col/4),underline); }
60
+uint16_t eia608_row_style_pramble (int row, eia608_style_t style, int chan, int underline) { return eia608_row_pramble (row,chan,style,underline); }
61
+
62
+int eia608_parse_preamble (uint16_t cc_data, int* row, int* col, eia608_style_t* style, int* chan, int* underline)
63
+{
64
+    (*row) = eia608_row_map[ ( (0x0700 & cc_data) >> 7) | ( (0x0020 & cc_data) >> 5)];
65
+    (*chan) = !! (0x0800 & cc_data);
66
+    (*underline) = 0x0001 & cc_data;
67
+
68
+    if (0x0010 & cc_data) {
69
+        (*style) = eia608_style_white;
70
+        (*col) = 4* ( (0x000E & cc_data) >> 1);
71
+    } else {
72
+        (*style) = (0x000E & cc_data) >> 1;
73
+        (*col) = 0;
74
+    }
75
+
76
+    return 1;
77
+}
78
+
79
+int eia608_parse_midrowchange (uint16_t cc_data, int* chan, eia608_style_t* style, int* underline)
80
+{
81
+    (*chan) = !! (0x0800 & cc_data);
82
+
83
+    if (0x1120 == (0x7770 & cc_data)) {
84
+        (*style) = (0x000E & cc_data) >> 1;
85
+        (*underline) = 0x0001 & cc_data;
86
+    }
87
+
88
+    return 1;
89
+}
90
+////////////////////////////////////////////////////////////////////////////////
91
+// control command
92
+eia608_control_t eia608_parse_control (uint16_t cc_data, int* cc)
93
+{
94
+    if (0x0200&cc_data) {
95
+        (*cc) = (cc_data&0x0800?0x01:0x00);
96
+        return (eia608_control_t) (0x177F & cc_data);
97
+    } else {
98
+        (*cc) = (cc_data&0x0800?0x01:0x00) | (cc_data&0x0100?0x02:0x00);
99
+        return (eia608_control_t) (0x167F & cc_data);
100
+    }
101
+}
102
+
103
+uint16_t eia608_control_command (eia608_control_t cmd, int cc)
104
+{
105
+    uint16_t c = (cc&0x01) ?0x0800:0x0000;
106
+    uint16_t f = (cc&0x02) ?0x0100:0x0000;
107
+
108
+    if (eia608_tab_offset_0 == (eia608_control_t) (cmd&0xFFC0)) {
109
+        return (eia608_control_t) eia608_parity (cmd|c);
110
+    } else {
111
+        return (eia608_control_t) eia608_parity (cmd|c|f);
112
+    }
113
+}
114
+////////////////////////////////////////////////////////////////////////////////
115
+// text
116
+static const char* utf8_from_index (int idx) { return (0<=idx && EIA608_CHAR_COUNT>idx) ? eia608_char_map[idx] : ""; }
117
+static int eia608_to_index (uint16_t cc_data, int* chan, int* c1, int* c2)
118
+{
119
+    (*c1) = (*c2) = -1; (*chan) = 0;
120
+    cc_data &= 0x7F7F; // strip off parity bits
121
+
122
+    // Handle Basic NA BEFORE we strip the channel bit
123
+    if (eia608_is_basicna (cc_data)) {
124
+        // we got first char, yes. But what about second char?
125
+        (*c1) = (cc_data>>8) - 0x20;
126
+        cc_data &= 0x00FF;
127
+
128
+        if (0x0020<=cc_data && 0x0080>cc_data) {
129
+            (*c2) = cc_data - 0x20;
130
+            return 2;
131
+        }
132
+
133
+        return 1;
134
+    }
135
+
136
+    // Check then strip second channel toggle
137
+    (*chan) = cc_data & 0x0800;
138
+    cc_data = cc_data & 0xF7FF;
139
+
140
+    if (eia608_is_specialna (cc_data)) {
141
+        // Special North American character
142
+        (*c1) = cc_data - 0x1130 + 0x60;
143
+        return 1;
144
+    }
145
+
146
+    if (0x1220<=cc_data && 0x1240>cc_data) {
147
+        // Extended Western European character set, Spanish/Miscellaneous/French
148
+        (*c1) = cc_data - 0x1220 + 0x70;
149
+        return 1;
150
+    }
151
+
152
+    if (0x1320<=cc_data && 0x1340>cc_data) {
153
+        // Extended Western European character set, Portuguese/German/Danish
154
+        (*c1) = cc_data - 0x1320 + 0x90;
155
+        return 1;
156
+    }
157
+
158
+    return 0;
159
+}
160
+
161
+
162
+int eia608_to_utf8 (uint16_t c, int* chan, char* str1,  char* str2)
163
+{
164
+    int c1, c2;
165
+    size_t size = eia608_to_index (c,chan,&c1,&c2);
166
+    strncpy (str1, utf8_from_index (c1),5);
167
+    strncpy (str2, utf8_from_index (c2),5);
168
+    return (int)size;
169
+}
170
+
171
+uint16_t eia608_from_basicna (uint16_t bna1, uint16_t bna2)
172
+{
173
+    if (! eia608_is_basicna (bna1) || ! eia608_is_basicna (bna2)) {
174
+        return 0;
175
+    }
176
+
177
+    return eia608_parity ( ( (0xFF00&bna1) >>0) | ( (0xFF00&bna2) >>8));
178
+}
179
+
180
+// prototype for re2c generated function
181
+uint16_t _eia608_from_utf8 (const utf8_char_t* s);
182
+uint16_t eia608_from_utf8_1 (const utf8_char_t* c, int chan)
183
+{
184
+    uint16_t cc_data = _eia608_from_utf8 (c);
185
+
186
+    if (0 == cc_data) {
187
+        return cc_data;
188
+    }
189
+
190
+    if (chan && ! eia608_is_basicna (cc_data)) {
191
+        cc_data |= 0x0800;
192
+    }
193
+
194
+    return eia608_parity (cc_data);
195
+}
196
+
197
+uint16_t eia608_from_utf8_2 (const utf8_char_t* c1, const utf8_char_t* c2)
198
+{
199
+    uint16_t cc1 = _eia608_from_utf8 (c1);
200
+    uint16_t cc2 = _eia608_from_utf8 (c2);
201
+    return eia608_from_basicna (cc1,cc2);
202
+}
203
+////////////////////////////////////////////////////////////////////////////////
204
+void eia608_dump (uint16_t cc_data)
205
+{
206
+    eia608_style_t style;
207
+    const char* text = 0;
208
+    char char1[5], char2[5];
209
+    char1[0] = char2[0] = 0;
210
+    int row, col, chan, underline;
211
+
212
+    if (!eia608_parity_varify (cc_data)) {
213
+        text = "parity failed";
214
+    } else if (0 == eia608_parity_strip (cc_data)) {
215
+        text = "pad";
216
+    } else if (eia608_is_basicna (cc_data)) {
217
+        text = "basicna";
218
+        eia608_to_utf8 (cc_data,&chan,&char1[0],&char2[0]);
219
+    } else if (eia608_is_specialna (cc_data)) {
220
+        text = "specialna";
221
+        eia608_to_utf8 (cc_data,&chan,&char1[0],&char2[0]);
222
+    } else if (eia608_is_westeu (cc_data)) {
223
+        text = "westeu";
224
+        eia608_to_utf8 (cc_data,&chan,&char1[0],&char2[0]);
225
+    } else if (eia608_is_xds (cc_data)) {
226
+        text = "xds";
227
+    } else if (eia608_is_midrowchange (cc_data)) {
228
+        text = "midrowchange";
229
+    } else if (eia608_is_norpak (cc_data)) {
230
+        text = "norpak";
231
+    } else if (eia608_is_preamble (cc_data)) {
232
+        text = "preamble";
233
+        eia608_parse_preamble (cc_data, &row, &col, &style, &chan, &underline);
234
+        fprintf (stderr,"preamble %d %d %d %d %d\n", row, col, style, chan, underline);
235
+
236
+    } else if (eia608_is_control (cc_data)) {
237
+        switch (eia608_parse_control (cc_data,&chan)) {
238
+
239
+        default: text = "unknown_control"; break;
240
+
241
+        case eia608_tab_offset_0: text = "eia608_tab_offset_0"; break;
242
+
243
+        case eia608_tab_offset_1: text = "eia608_tab_offset_1"; break;
244
+
245
+        case eia608_tab_offset_2:text = "eia608_tab_offset_2"; break;
246
+
247
+        case eia608_tab_offset_3: text = "eia608_tab_offset_3"; break;
248
+
249
+        case eia608_control_resume_caption_loading: text = "eia608_control_resume_caption_loading"; break;
250
+
251
+        case eia608_control_backspace: text = "eia608_control_backspace"; break;
252
+
253
+        case eia608_control_alarm_off: text = "eia608_control_alarm_off"; break;
254
+
255
+        case eia608_control_alarm_on: text = "eia608_control_alarm_on"; break;
256
+
257
+        case eia608_control_delete_to_end_of_row: text = "eia608_control_delete_to_end_of_row"; break;
258
+
259
+        case eia608_control_roll_up_2: text = "eia608_control_roll_up_2"; break;
260
+
261
+        case eia608_control_roll_up_3: text = "eia608_control_roll_up_3"; break;
262
+
263
+        case eia608_control_roll_up_4: text = "eia608_control_roll_up_4"; break;
264
+
265
+        case eia608_control_resume_direct_captioning: text = "eia608_control_resume_direct_captioning"; break;
266
+
267
+        case eia608_control_text_restart: text = "eia608_control_text_restart"; break;
268
+
269
+        case eia608_control_text_resume_text_display: text = "eia608_control_text_resume_text_display"; break;
270
+
271
+        case eia608_control_erase_display_memory: text = "eia608_control_erase_display_memory"; break;
272
+
273
+        case eia608_control_carriage_return: text = "eia608_control_carriage_return"; break;
274
+
275
+        case eia608_control_erase_non_displayed_memory:text = "eia608_control_erase_non_displayed_memory"; break;
276
+
277
+        case eia608_control_end_of_caption: text = "eia608_control_end_of_caption"; break;
278
+        }
279
+    } else {
280
+        text = "unhandled";
281
+    }
282
+
283
+    fprintf (stderr,"cc %04X (%04X) '%s' '%s' (%s)\n", cc_data, eia608_parity_strip (cc_data), char1, char2, text);
284
+}
285
+////////////////////////////////////////////////////////////////////////////////
286
+// below this line is re2c
287
+uint16_t _eia608_from_utf8 (const utf8_char_t* s)
288
+{
289
+    const unsigned char* YYMARKER; // needed by default rule
290
+    const unsigned char* YYCURSOR = (const unsigned char*) s;
291
+
292
+    if (0==s) { return 0x0000;}
293
+
294
+    
295
+{
296
+    unsigned char yych;
297
+    yych = *YYCURSOR;
298
+    if (yych <= '`') {
299
+        if (yych <= '*') {
300
+            if (yych <= '&') {
301
+                if (yych <= 0x00) goto yy2;
302
+                if (yych <= 0x1F) goto yy32;
303
+                goto yy26;
304
+            } else {
305
+                if (yych <= '\'') goto yy4;
306
+                if (yych <= ')') goto yy26;
307
+                goto yy6;
308
+            }
309
+        } else {
310
+            if (yych <= ']') {
311
+                if (yych == '\\') goto yy8;
312
+                goto yy26;
313
+            } else {
314
+                if (yych <= '^') goto yy10;
315
+                if (yych <= '_') goto yy12;
316
+                goto yy14;
317
+            }
318
+        }
319
+    } else {
320
+        if (yych <= 0x7F) {
321
+            if (yych <= '|') {
322
+                if (yych <= 'z') goto yy26;
323
+                if (yych <= '{') goto yy16;
324
+                goto yy18;
325
+            } else {
326
+                if (yych <= '}') goto yy20;
327
+                if (yych <= '~') goto yy22;
328
+                goto yy24;
329
+            }
330
+        } else {
331
+            if (yych <= 0xC3) {
332
+                if (yych <= 0xC1) goto yy32;
333
+                if (yych <= 0xC2) goto yy31;
334
+                goto yy28;
335
+            } else {
336
+                if (yych == 0xE2) goto yy30;
337
+                goto yy32;
338
+            }
339
+        }
340
+    }
341
+yy2:
342
+    ++YYCURSOR;
343
+    { /*NULL*/ return 0x0000; }
344
+yy4:
345
+    ++YYCURSOR;
346
+    { /*APOSTROPHE -> RIGHT_SINGLE_QUOTATION_MARK*/ return 0x1229; }
347
+yy6:
348
+    ++YYCURSOR;
349
+    { /*ASTERISK*/ return 0x1228; }
350
+yy8:
351
+    ++YYCURSOR;
352
+    { /*REVERSE_SOLIDUS*/ return 0x132B; }
353
+yy10:
354
+    ++YYCURSOR;
355
+    { /*CIRCUMFLEX_ACCENT*/ return 0x132C; }
356
+yy12:
357
+    ++YYCURSOR;
358
+    { /*LOW_LINE*/ return 0x132D; }
359
+yy14:
360
+    ++YYCURSOR;
361
+    { /*GRAVE_ACCENT, No equivalent return 0x0000; return 1;*/ /*LEFT_SINGLE_QUOTATION_MARK*/ return 0x1226; }
362
+yy16:
363
+    ++YYCURSOR;
364
+    { /*LEFT_CURLY_BRACKET*/ return 0x1329; }
365
+yy18:
366
+    ++YYCURSOR;
367
+    { /*VERTICAL_LINE*/ return 0x132E; }
368
+yy20:
369
+    ++YYCURSOR;
370
+    { /*RIGHT_CURLY_BRACKET*/ return 0x132A; }
371
+yy22:
372
+    ++YYCURSOR;
373
+    { /*TILDE*/ return 0x132F; }
374
+yy24:
375
+    ++YYCURSOR;
376
+    { /*DEL/BACKSPACE. Need to set bits 9 and 12! return 0x1421;*/ return 0x0000; }
377
+yy26:
378
+    ++YYCURSOR;
379
+    { /*ASCII range*/ return (s[0]<<8) &0xFF00; }
380
+yy28:
381
+    ++YYCURSOR;
382
+    switch ((yych = *YYCURSOR)) {
383
+    case 0x80:    goto yy157;
384
+    case 0x81:    goto yy169;
385
+    case 0x82:    goto yy155;
386
+    case 0x83:    goto yy129;
387
+    case 0x84:    goto yy111;
388
+    case 0x85:    goto yy101;
389
+    case 0x87:    goto yy153;
390
+    case 0x88:    goto yy151;
391
+    case 0x89:    goto yy167;
392
+    case 0x8A:    goto yy149;
393
+    case 0x8B:    goto yy147;
394
+    case 0x8C:    goto yy123;
395
+    case 0x8D:    goto yy125;
396
+    case 0x8E:    goto yy143;
397
+    case 0x8F:    goto yy141;
398
+    case 0x91:    goto yy187;
399
+    case 0x92:    goto yy119;
400
+    case 0x93:    goto yy165;
401
+    case 0x94:    goto yy137;
402
+    case 0x95:    goto yy115;
403
+    case 0x96:    goto yy107;
404
+    case 0x98:    goto yy97;
405
+    case 0x99:    goto yy135;
406
+    case 0x9A:    goto yy163;
407
+    case 0x9B:    goto yy131;
408
+    case 0x9C:    goto yy161;
409
+    case 0x9F:    goto yy103;
410
+    case 0xA0:    goto yy183;
411
+    case 0xA1:    goto yy201;
412
+    case 0xA2:    goto yy179;
413
+    case 0xA3:    goto yy127;
414
+    case 0xA4:    goto yy109;
415
+    case 0xA5:    goto yy99;
416
+    case 0xA7:    goto yy191;
417
+    case 0xA8:    goto yy181;
418
+    case 0xA9:    goto yy199;
419
+    case 0xAA:    goto yy177;
420
+    case 0xAB:    goto yy145;
421
+    case 0xAC:    goto yy121;
422
+    case 0xAD:    goto yy197;
423
+    case 0xAE:    goto yy175;
424
+    case 0xAF:    goto yy139;
425
+    case 0xB1:    goto yy185;
426
+    case 0xB2:    goto yy117;
427
+    case 0xB3:    goto yy195;
428
+    case 0xB4:    goto yy173;
429
+    case 0xB5:    goto yy113;
430
+    case 0xB6:    goto yy105;
431
+    case 0xB7:    goto yy189;
432
+    case 0xB8:    goto yy95;
433
+    case 0xB9:    goto yy133;
434
+    case 0xBA:    goto yy193;
435
+    case 0xBB:    goto yy171;
436
+    case 0xBC:    goto yy159;
437
+    default:    goto yy29;
438
+    }
439
+yy29:
440
+    { /*DEFAULT_RULE*/ return 0x0000; }
441
+yy30:
442
+    yych = *(YYMARKER = ++YYCURSOR);
443
+    switch (yych) {
444
+    case 0x80:    goto yy63;
445
+    case 0x84:    goto yy64;
446
+    case 0x94:    goto yy61;
447
+    case 0x96:    goto yy66;
448
+    case 0x99:    goto yy65;
449
+    default:    goto yy29;
450
+    }
451
+yy31:
452
+    yych = *++YYCURSOR;
453
+    switch (yych) {
454
+    case 0xA0:    goto yy47;
455
+    case 0xA1:    goto yy45;
456
+    case 0xA2:    goto yy51;
457
+    case 0xA3:    goto yy49;
458
+    case 0xA4:    goto yy35;
459
+    case 0xA5:    goto yy37;
460
+    case 0xA6:    goto yy33;
461
+    case 0xA9:    goto yy43;
462
+    case 0xAB:    goto yy41;
463
+    case 0xAE:    goto yy59;
464
+    case 0xB0:    goto yy57;
465
+    case 0xBB:    goto yy39;
466
+    case 0xBD:    goto yy55;
467
+    case 0xBF:    goto yy53;
468
+    default:    goto yy29;
469
+    }
470
+yy32:
471
+    yych = *++YYCURSOR;
472
+    goto yy29;
473
+yy33:
474
+    ++YYCURSOR;
475
+    { /*BROKEN_BAR*/ return 0x1337; }
476
+yy35:
477
+    ++YYCURSOR;
478
+    { /*CURRENCY_SIGN*/ return 0x1336; }
479
+yy37:
480
+    ++YYCURSOR;
481
+    { /*YEN_SIGN*/ return 0x1335; }
482
+yy39:
483
+    ++YYCURSOR;
484
+    { /*RIGHT_POINTING_DOUBLE_ANGLE_QUOTATION_MARK*/ return 0x123F; }
485
+yy41:
486
+    ++YYCURSOR;
487
+    { /*LEFT_POINTING_DOUBLE_ANGLE_QUOTATION_MARK*/ return 0x123E; }
488
+yy43:
489
+    ++YYCURSOR;
490
+    { /*COPYRIGHT_SIGN*/ return 0x122B; }
491
+yy45:
492
+    ++YYCURSOR;
493
+    { /*INVERTED_EXCLAMATION_MARK*/ return 0x1227; }
494
+yy47:
495
+    ++YYCURSOR;
496
+    { /*NO_BREAK_SPACE*/ return 0x1139; }
497
+yy49:
498
+    ++YYCURSOR;
499
+    { /*POUND_SIGN*/ return 0x1136; }
500
+yy51:
501
+    ++YYCURSOR;
502
+    { /*CENT_SIGN*/ return 0x1135; }
503
+yy53:
504
+    ++YYCURSOR;
505
+    { /*INVERTED_QUESTION_MARK*/ return 0x1133; }
506
+yy55:
507
+    ++YYCURSOR;
508
+    { /*VULGAR_FRACTION_ONE_HALF*/ return 0x1132; }
509
+yy57:
510
+    ++YYCURSOR;
511
+    { /*DEGREE_SIGN*/ return 0x1131; }
512
+yy59:
513
+    ++YYCURSOR;
514
+    { /*REGISTERED_SIGN*/ return 0x1130; }
515
+yy61:
516
+    yych = *++YYCURSOR;
517
+    switch (yych) {
518
+    case 0x8C:    goto yy87;
519
+    case 0x90:    goto yy89;
520
+    case 0x94:    goto yy91;
521
+    case 0x98:    goto yy93;
522
+    default:    goto yy62;
523
+    }
524
+yy62:
525
+    YYCURSOR = YYMARKER;
526
+    goto yy29;
527
+yy63:
528
+    yych = *++YYCURSOR;
529
+    switch (yych) {
530
+    case 0x94:    goto yy79;
531
+    case 0x98:    goto yy75;
532
+    case 0x99:    goto yy77;
533
+    case 0x9C:    goto yy83;
534
+    case 0x9D:    goto yy85;
535
+    case 0xA2:    goto yy81;
536
+    default:    goto yy62;
537
+    }
538
+yy64:
539
+    yych = *++YYCURSOR;
540
+    if (yych == 0xA0) goto yy73;
541
+    if (yych == 0xA2) goto yy71;
542
+    goto yy62;
543
+yy65:
544
+    yych = *++YYCURSOR;
545
+    if (yych == 0xAA) goto yy69;
546
+    goto yy62;
547
+yy66:
548
+    yych = *++YYCURSOR;
549
+    if (yych != 0x88) goto yy62;
550
+    ++YYCURSOR;
551
+    { /*FULL_BLOCK*/ return 0x7F00; }
552
+yy69:
553
+    ++YYCURSOR;
554
+    { /*EIGHTH_NOTE*/ return 0x1137; }
555
+yy71:
556
+    ++YYCURSOR;
557
+    { /*TRADE_MARK_SIGN*/ return 0x1134; }
558
+yy73:
559
+    ++YYCURSOR;
560
+    { /*SERVICE_MARK*/ return 0x122C; }
561
+yy75:
562
+    ++YYCURSOR;
563
+    { /*LEFT_SINGLE_QUOTATION_MARK*/ return 0x1226; }
564
+yy77:
565
+    ++YYCURSOR;
566
+    { /*RIGHT_SINGLE_QUOTATION_MARK -> APOSTROPHE*/ return 0x2700; }
567
+yy79:
568
+    ++YYCURSOR;
569
+    { /*EM_DASH*/ return 0x122A; }
570
+yy81:
571
+    ++YYCURSOR;
572
+    { /*BULLET*/ return 0x122D; }
573
+yy83:
574
+    ++YYCURSOR;
575
+    { /*LEFT_DOUBLE_QUOTATION_MARK*/ return 0x122E; }
576
+yy85:
577
+    ++YYCURSOR;
578
+    { /*RIGHT_DOUBLE_QUOTATION_MARK*/ return 0x122F; }
579
+yy87:
580
+    ++YYCURSOR;
581
+    { /*EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_RIGHT*/ return 0x133C; }
582
+yy89:
583
+    ++YYCURSOR;
584
+    { /*EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_LEFT*/ return 0x133D; }
585
+yy91:
586
+    ++YYCURSOR;
587
+    { /*EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_RIGHT*/ return 0x133E; }
588
+yy93:
589
+    ++YYCURSOR;
590
+    { /*EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_LEFT*/ return 0x133F; }
591
+yy95:
592
+    ++YYCURSOR;
593
+    { /*LATIN_SMALL_LETTER_O_WITH_STROKE*/ return 0x133B; }
594
+yy97:
595
+    ++YYCURSOR;
596
+    { /*LATIN_CAPITAL_LETTER_O_WITH_STROKE*/ return 0x133A; }
597
+yy99:
598
+    ++YYCURSOR;
599
+    { /*LATIN_SMALL_LETTER_A_WITH_RING_ABOVE*/ return 0x1339; }
600
+yy101:
601
+    ++YYCURSOR;
602
+    { /*LATIN_CAPITAL_LETTER_A_WITH_RING_ABOVE*/ return 0x1338; }
603
+yy103:
604
+    ++YYCURSOR;
605
+    { /*LATIN_SMALL_LETTER_SHARP_S*/ return 0x1334; }
606
+yy105:
607
+    ++YYCURSOR;
608
+    { /*LATIN_SMALL_LETTER_O_WITH_DIAERESIS*/ return 0x1333; }
609
+yy107:
610
+    ++YYCURSOR;
611
+    { /*LATIN_CAPITAL_LETTER_O_WITH_DIAERESIS*/ return 0x1332; }
612
+yy109:
613
+    ++YYCURSOR;
614
+    { /*LATIN_SMALL_LETTER_A_WITH_DIAERESIS*/ return 0x1331; }
615
+yy111:
616
+    ++YYCURSOR;
617
+    { /*LATIN_CAPITAL_LETTER_A_WITH_DIAERESIS*/ return 0x1330; }
618
+yy113:
619
+    ++YYCURSOR;
620
+    { /*LATIN_SMALL_LETTER_O_WITH_TILDE*/ return 0x1328; }
621
+yy115:
622
+    ++YYCURSOR;
623
+    { /*LATIN_CAPITAL_LETTER_O_WITH_TILDE*/ return 0x1327; }
624
+yy117:
625
+    ++YYCURSOR;
626
+    { /*LATIN_SMALL_LETTER_O_WITH_GRAVE*/ return 0x1326; }
627
+yy119:
628
+    ++YYCURSOR;
629
+    { /*LATIN_CAPITAL_LETTER_O_WITH_GRAVE*/ return 0x1325; }
630
+yy121:
631
+    ++YYCURSOR;
632
+    { /*LATIN_SMALL_LETTER_I_WITH_GRAVE*/ return 0x1324; }
633
+yy123:
634
+    ++YYCURSOR;
635
+    { /*LATIN_CAPITAL_LETTER_I_WITH_GRAVE*/ return 0x1323; }
636
+yy125:
637
+    ++YYCURSOR;
638
+    { /*LATIN_CAPITAL_LETTER_I_WITH_ACUTE*/ return 0x1322; }
639
+yy127:
640
+    ++YYCURSOR;
641
+    { /*LATIN_SMALL_LETTER_A_WITH_TILDE*/ return 0x1321; }
642
+yy129:
643
+    ++YYCURSOR;
644
+    { /*LATIN_CAPITAL_LETTER_A_WITH_TILDE*/ return 0x1320; }
645
+yy131:
646
+    ++YYCURSOR;
647
+    { /*LATIN_CAPITAL_LETTER_U_WITH_CIRCUMFLEX*/ return 0x123D; }
648
+yy133:
649
+    ++YYCURSOR;
650
+    { /*LATIN_SMALL_LETTER_U_WITH_GRAVE*/ return 0x123C; }
651
+yy135:
652
+    ++YYCURSOR;
653
+    { /*LATIN_CAPITAL_LETTER_U_WITH_GRAVE*/ return 0x123B; }
654
+yy137:
655
+    ++YYCURSOR;
656
+    { /*LATIN_CAPITAL_LETTER_O_WITH_CIRCUMFLEX*/ return 0x123A; }
657
+yy139:
658
+    ++YYCURSOR;
659
+    { /*LATIN_SMALL_LETTER_I_WITH_DIAERESIS*/ return 0x1239; }
660
+yy141:
661
+    ++YYCURSOR;
662
+    { /*LATIN_CAPITAL_LETTER_I_WITH_DIAERESIS*/ return 0x1238; }
663
+yy143:
664
+    ++YYCURSOR;
665
+    { /*LATIN_CAPITAL_LETTER_I_WITH_CIRCUMFLEX*/ return 0x1237; }
666
+yy145:
667
+    ++YYCURSOR;
668
+    { /*LATIN_SMALL_LETTER_E_WITH_DIAERESIS*/ return 0x1236; }
669
+yy147:
670
+    ++YYCURSOR;
671
+    { /*LATIN_CAPITAL_LETTER_E_WITH_DIAERESIS*/ return 0x1235; }
672
+yy149:
673
+    ++YYCURSOR;
674
+    { /*LATIN_CAPITAL_LETTER_E_WITH_CIRCUMFLEX*/ return 0x1234; }
675
+yy151:
676
+    ++YYCURSOR;
677
+    { /*LATIN_CAPITAL_LETTER_E_WITH_GRAVE*/ return 0x1233; }
678
+yy153:
679
+    ++YYCURSOR;
680
+    { /*LATIN_CAPITAL_LETTER_C_WITH_CEDILLA*/ return 0x1232; }
681
+yy155:
682
+    ++YYCURSOR;
683
+    { /*LATIN_CAPITAL_LETTER_A_WITH_CIRCUMFLEX*/ return 0x1231; }
684
+yy157:
685
+    ++YYCURSOR;
686
+    { /*LATIN_CAPITAL_LETTER_A_WITH_GRAVE*/ return 0x1230; }
687
+yy159:
688
+    ++YYCURSOR;
689
+    { /*LATIN_SMALL_LETTER_U_WITH_DIAERESIS*/ return 0x1225; }
690
+yy161:
691
+    ++YYCURSOR;
692
+    { /*LATIN_CAPITAL_LETTER_U_WITH_DIAERESIS*/ return 0x1224; }
693
+yy163:
694
+    ++YYCURSOR;
695
+    { /*LATIN_CAPITAL_LETTER_U_WITH_ACUTE*/ return 0x1223; }
696
+yy165:
697
+    ++YYCURSOR;
698
+    { /*LATIN_CAPITAL_LETTER_O_WITH_ACUTE*/ return 0x1222; }
699
+yy167:
700
+    ++YYCURSOR;
701
+    { /*LATIN_CAPITAL_LETTER_E_WITH_ACUTE*/ return 0x1221; }
702
+yy169:
703
+    ++YYCURSOR;
704
+    { /*LATIN_CAPITAL_LETTER_A_WITH_ACUTE*/ return 0x1220; }
705
+yy171:
706
+    ++YYCURSOR;
707
+    { /*LATIN_SMALL_LETTER_U_WITH_CIRCUMFLEX*/ return 0x113F; }
708
+yy173:
709
+    ++YYCURSOR;
710
+    { /*LATIN_SMALL_LETTER_O_WITH_CIRCUMFLEX*/ return 0x113E; }
711
+yy175:
712
+    ++YYCURSOR;
713
+    { /*LATIN_SMALL_LETTER_I_WITH_CIRCUMFLEX*/ return 0x113D; }
714
+yy177:
715
+    ++YYCURSOR;
716
+    { /*LATIN_SMALL_LETTER_E_WITH_CIRCUMFLEX*/ return 0x113C; }
717
+yy179:
718
+    ++YYCURSOR;
719
+    { /*LATIN_SMALL_LETTER_A_WITH_CIRCUMFLEX*/ return 0x113B; }
720
+yy181:
721
+    ++YYCURSOR;
722
+    { /*LATIN_SMALL_LETTER_E_WITH_GRAVE*/ return 0x113A; }
723
+yy183:
724
+    ++YYCURSOR;
725
+    { /*LATIN_SMALL_LETTER_A_WITH_GRAVE*/ return 0x1138; }
726
+yy185:
727
+    ++YYCURSOR;
728
+    { /*LATIN_SMALL_LETTER_N_WITH_TILDE*/ return 0x7E00; }
729
+yy187:
730
+    ++YYCURSOR;
731
+    { /*LATIN_CAPITAL_LETTER_N_WITH_TILDE*/ return 0x7D00; }
732
+yy189:
733
+    ++YYCURSOR;
734
+    { /*DIVISION_SIGN*/ return 0x7C00; }
735
+yy191:
736
+    ++YYCURSOR;
737
+    { /*LATIN_SMALL_LETTER_C_WITH_CEDILLA*/ return 0x7B00; }
738
+yy193:
739
+    ++YYCURSOR;
740
+    { /*LATIN_SMALL_LETTER_U_WITH_ACUTE*/ return 0x6000; }
741
+yy195:
742
+    ++YYCURSOR;
743
+    { /*LATIN_SMALL_LETTER_O_WITH_ACUTE*/ return 0x5F00; }
744
+yy197:
745
+    ++YYCURSOR;
746
+    { /*LATIN_SMALL_LETTER_I_WITH_ACUTE*/ return 0x5E00; }
747
+yy199:
748
+    ++YYCURSOR;
749
+    { /*LATIN_SMALL_LETTER_E_WITH_ACUTE*/ return 0x5C00; }
750
+yy201:
751
+    ++YYCURSOR;
752
+    { /*LATIN_SMALL_LETTER_A_WITH_ACUTE*/ return 0x2A00; }
753
+}
754
+
755
+}
756
obs-studio-0.17.0.tar.xz/deps/libcaption/src/eia608.c.re2c Added
423
 
1
@@ -0,0 +1,421 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#include "eia608.h"
26
+#include <string.h>
27
+#include <stdio.h>
28
+
29
+////////////////////////////////////////////////////////////////////////////////
30
+int eia608_row_map[] = {10, -1, 0, 1, 2, 3, 11, 12, 13, 14, 4, 5, 6, 7, 8, 9};
31
+int eia608_reverse_row_map[] = {2, 3, 4, 5, 10, 11, 12, 13, 14, 15, 0, 6, 7, 8, 9, 1};
32
+
33
+const char* eia608_mode_map[] = {
34
+    "clear",
35
+    "loading",
36
+    "popOn",
37
+    "paintOn",
38
+    "rollUp",
39
+};
40
+
41
+const char* eia608_style_map[] = {
42
+    "white",
43
+    "green",
44
+    "blue",
45
+    "cyan",
46
+    "red",
47
+    "yellow",
48
+    "magenta",
49
+    "italics",
50
+};
51
+
52
+static inline uint16_t eia608_row_pramble (int row, int chan, int x, int underline)
53
+{
54
+    row = eia608_reverse_row_map[row&0x0F];
55
+    return eia608_parity (0x1040 | (chan?0x0800:0x0000) | ( (row<<7) &0x0700) | ( (row<<5) &0x0020)) | ( (x<<1) &0x001E) | (underline?0x0001:0x0000);
56
+}
57
+
58
+uint16_t eia608_row_column_pramble (int row, int col, int chan, int underline) { return eia608_row_pramble (row,chan,0x10| (col/4),underline); }
59
+uint16_t eia608_row_style_pramble (int row, eia608_style_t style, int chan, int underline) { return eia608_row_pramble (row,chan,style,underline); }
60
+
61
+int eia608_parse_preamble (uint16_t cc_data, int* row, int* col, eia608_style_t* style, int* chan, int* underline)
62
+{
63
+    (*row) = eia608_row_map[ ( (0x0700 & cc_data) >> 7) | ( (0x0020 & cc_data) >> 5)];
64
+    (*chan) = !! (0x0800 & cc_data);
65
+    (*underline) = 0x0001 & cc_data;
66
+
67
+    if (0x0010 & cc_data) {
68
+        (*style) = eia608_style_white;
69
+        (*col) = 4* ( (0x000E & cc_data) >> 1);
70
+    } else {
71
+        (*style) = (0x000E & cc_data) >> 1;
72
+        (*col) = 0;
73
+    }
74
+
75
+    return 1;
76
+}
77
+
78
+int eia608_parse_midrowchange (uint16_t cc_data, int* chan, eia608_style_t* style, int* underline)
79
+{
80
+    (*chan) = !! (0x0800 & cc_data);
81
+
82
+    if (0x1120 == (0x7770 & cc_data)) {
83
+        (*style) = (0x000E & cc_data) >> 1;
84
+        (*underline) = 0x0001 & cc_data;
85
+    }
86
+
87
+    return 1;
88
+}
89
+////////////////////////////////////////////////////////////////////////////////
90
+// control command
91
+eia608_control_t eia608_parse_control (uint16_t cc_data, int* cc)
92
+{
93
+    if (0x0200&cc_data) {
94
+        (*cc) = (cc_data&0x0800?0x01:0x00);
95
+        return (eia608_control_t) (0x177F & cc_data);
96
+    } else {
97
+        (*cc) = (cc_data&0x0800?0x01:0x00) | (cc_data&0x0100?0x02:0x00);
98
+        return (eia608_control_t) (0x167F & cc_data);
99
+    }
100
+}
101
+
102
+uint16_t eia608_control_command (eia608_control_t cmd, int cc)
103
+{
104
+    uint16_t c = (cc&0x01) ?0x0800:0x0000;
105
+    uint16_t f = (cc&0x02) ?0x0100:0x0000;
106
+
107
+    if (eia608_tab_offset_0 == (eia608_control_t) (cmd&0xFFC0)) {
108
+        return (eia608_control_t) eia608_parity (cmd|c);
109
+    } else {
110
+        return (eia608_control_t) eia608_parity (cmd|c|f);
111
+    }
112
+}
113
+////////////////////////////////////////////////////////////////////////////////
114
+// text
115
+static const char* utf8_from_index (int idx) { return (0<=idx && EIA608_CHAR_COUNT>idx) ? eia608_char_map[idx] : ""; }
116
+static int eia608_to_index (uint16_t cc_data, int* chan, int* c1, int* c2)
117
+{
118
+    (*c1) = (*c2) = -1; (*chan) = 0;
119
+    cc_data &= 0x7F7F; // strip off parity bits
120
+
121
+    // Handle Basic NA BEFORE we strip the channel bit
122
+    if (eia608_is_basicna (cc_data)) {
123
+        // we got first char, yes. But what about second char?
124
+        (*c1) = (cc_data>>8) - 0x20;
125
+        cc_data &= 0x00FF;
126
+
127
+        if (0x0020<=cc_data && 0x0080>cc_data) {
128
+            (*c2) = cc_data - 0x20;
129
+            return 2;
130
+        }
131
+
132
+        return 1;
133
+    }
134
+
135
+    // Check then strip second channel toggle
136
+    (*chan) = cc_data & 0x0800;
137
+    cc_data = cc_data & 0xF7FF;
138
+
139
+    if (eia608_is_specialna (cc_data)) {
140
+        // Special North American character
141
+        (*c1) = cc_data - 0x1130 + 0x60;
142
+        return 1;
143
+    }
144
+
145
+    if (0x1220<=cc_data && 0x1240>cc_data) {
146
+        // Extended Western European character set, Spanish/Miscellaneous/French
147
+        (*c1) = cc_data - 0x1220 + 0x70;
148
+        return 1;
149
+    }
150
+
151
+    if (0x1320<=cc_data && 0x1340>cc_data) {
152
+        // Extended Western European character set, Portuguese/German/Danish
153
+        (*c1) = cc_data - 0x1320 + 0x90;
154
+        return 1;
155
+    }
156
+
157
+    return 0;
158
+}
159
+
160
+
161
+int eia608_to_utf8 (uint16_t c, int* chan, char* str1,  char* str2)
162
+{
163
+    int c1, c2;
164
+    int size = (int) eia608_to_index (c,chan,&c1,&c2);
165
+    strncpy (str1, utf8_from_index (c1),5);
166
+    strncpy (str2, utf8_from_index (c2),5);
167
+    return size;
168
+}
169
+
170
+uint16_t eia608_from_basicna (uint16_t bna1, uint16_t bna2)
171
+{
172
+    if (! eia608_is_basicna (bna1) || ! eia608_is_basicna (bna2)) {
173
+        return 0;
174
+    }
175
+
176
+    return eia608_parity ( ( (0xFF00&bna1) >>0) | ( (0xFF00&bna2) >>8));
177
+}
178
+
179
+// prototype for re2c generated function
180
+uint16_t _eia608_from_utf8 (const utf8_char_t* s);
181
+uint16_t eia608_from_utf8_1 (const utf8_char_t* c, int chan)
182
+{
183
+    uint16_t cc_data = _eia608_from_utf8 (c);
184
+
185
+    if (0 == cc_data) {
186
+        return cc_data;
187
+    }
188
+
189
+    if (chan && ! eia608_is_basicna (cc_data)) {
190
+        cc_data |= 0x0800;
191
+    }
192
+
193
+    return eia608_parity (cc_data);
194
+}
195
+
196
+uint16_t eia608_from_utf8_2 (const utf8_char_t* c1, const utf8_char_t* c2)
197
+{
198
+    uint16_t cc1 = _eia608_from_utf8 (c1);
199
+    uint16_t cc2 = _eia608_from_utf8 (c2);
200
+    return eia608_from_basicna (cc1,cc2);
201
+}
202
+////////////////////////////////////////////////////////////////////////////////
203
+void eia608_dump (uint16_t cc_data)
204
+{
205
+    eia608_style_t style;
206
+    const char* text = 0;
207
+    char char1[5], char2[5];
208
+    char1[0] = char2[0] = 0;
209
+    int row, col, chan, underline;
210
+
211
+    if (!eia608_parity_varify (cc_data)) {
212
+        text = "parity failed";
213
+    } else if (0 == eia608_parity_strip (cc_data)) {
214
+        text = "pad";
215
+    } else if (eia608_is_basicna (cc_data)) {
216
+        text = "basicna";
217
+        eia608_to_utf8 (cc_data,&chan,&char1[0],&char2[0]);
218
+    } else if (eia608_is_specialna (cc_data)) {
219
+        text = "specialna";
220
+        eia608_to_utf8 (cc_data,&chan,&char1[0],&char2[0]);
221
+    } else if (eia608_is_westeu (cc_data)) {
222
+        text = "westeu";
223
+        eia608_to_utf8 (cc_data,&chan,&char1[0],&char2[0]);
224
+    } else if (eia608_is_xds (cc_data)) {
225
+        text = "xds";
226
+    } else if (eia608_is_midrowchange (cc_data)) {
227
+        text = "midrowchange";
228
+    } else if (eia608_is_norpak (cc_data)) {
229
+        text = "norpak";
230
+    } else if (eia608_is_preamble (cc_data)) {
231
+        text = "preamble";
232
+        eia608_parse_preamble (cc_data, &row, &col, &style, &chan, &underline);
233
+        fprintf (stderr,"preamble %d %d %d %d %d\n", row, col, style, chan, underline);
234
+
235
+    } else if (eia608_is_control (cc_data)) {
236
+        switch (eia608_parse_control (cc_data,&chan)) {
237
+
238
+        default: text = "unknown_control"; break;
239
+
240
+        case eia608_tab_offset_0: text = "eia608_tab_offset_0"; break;
241
+
242
+        case eia608_tab_offset_1: text = "eia608_tab_offset_1"; break;
243
+
244
+        case eia608_tab_offset_2:text = "eia608_tab_offset_2"; break;
245
+
246
+        case eia608_tab_offset_3: text = "eia608_tab_offset_3"; break;
247
+
248
+        case eia608_control_resume_caption_loading: text = "eia608_control_resume_caption_loading"; break;
249
+
250
+        case eia608_control_backspace: text = "eia608_control_backspace"; break;
251
+
252
+        case eia608_control_alarm_off: text = "eia608_control_alarm_off"; break;
253
+
254
+        case eia608_control_alarm_on: text = "eia608_control_alarm_on"; break;
255
+
256
+        case eia608_control_delete_to_end_of_row: text = "eia608_control_delete_to_end_of_row"; break;
257
+
258
+        case eia608_control_roll_up_2: text = "eia608_control_roll_up_2"; break;
259
+
260
+        case eia608_control_roll_up_3: text = "eia608_control_roll_up_3"; break;
261
+
262
+        case eia608_control_roll_up_4: text = "eia608_control_roll_up_4"; break;
263
+
264
+        case eia608_control_resume_direct_captioning: text = "eia608_control_resume_direct_captioning"; break;
265
+
266
+        case eia608_control_text_restart: text = "eia608_control_text_restart"; break;
267
+
268
+        case eia608_control_text_resume_text_display: text = "eia608_control_text_resume_text_display"; break;
269
+
270
+        case eia608_control_erase_display_memory: text = "eia608_control_erase_display_memory"; break;
271
+
272
+        case eia608_control_carriage_return: text = "eia608_control_carriage_return"; break;
273
+
274
+        case eia608_control_erase_non_displayed_memory:text = "eia608_control_erase_non_displayed_memory"; break;
275
+
276
+        case eia608_control_end_of_caption: text = "eia608_control_end_of_caption"; break;
277
+        }
278
+    } else {
279
+        text = "unhandled";
280
+    }
281
+
282
+    fprintf (stderr,"cc %04X (%04X) '%s' '%s' (%s)\n", cc_data, eia608_parity_strip (cc_data), char1, char2, text);
283
+}
284
+////////////////////////////////////////////////////////////////////////////////
285
+// below this line is re2c
286
+uint16_t _eia608_from_utf8 (const utf8_char_t* s)
287
+{
288
+    const unsigned char* YYMARKER; // needed by default rule
289
+    const unsigned char* YYCURSOR = (const unsigned char*) s;
290
+
291
+    if (0==s) { return 0x0000;}
292
+
293
+    /*!re2c
294
+    re2c:yyfill:enable = 0;
295
+    re2c:indent:string = "    ";
296
+    re2c:define:YYCTYPE = "unsigned char";
297
+
298
+    /*Ascii Exceptions*/
299
+    "\x00" { /*NULL*/ return 0x0000; }
300
+    "\x27" { /*APOSTROPHE -> RIGHT_SINGLE_QUOTATION_MARK*/ return 0x1229; }
301
+    "\x2A" { /*ASTERISK*/ return 0x1228; }
302
+    "\x5C" { /*REVERSE_SOLIDUS*/ return 0x132B; }
303
+    "\x5E" { /*CIRCUMFLEX_ACCENT*/ return 0x132C; }
304
+    "\x5F" { /*LOW_LINE*/ return 0x132D; }
305
+    /*Lets Map this to a LEFT_SINGLE_QUOTATION_MARK, just so we have a cc_data for every printable ASCII value*/
306
+    "\x60" { /*GRAVE_ACCENT, No equivalent return 0x0000; return 1;*/ /*LEFT_SINGLE_QUOTATION_MARK*/ return 0x1226; }
307
+    "\x7B" { /*LEFT_CURLY_BRACKET*/ return 0x1329; }
308
+    "\x7C" { /*VERTICAL_LINE*/ return 0x132E; }
309
+    "\x7D" { /*RIGHT_CURLY_BRACKET*/ return 0x132A; }
310
+    "\x7E" { /*TILDE*/ return 0x132F; }
311
+    /*There is a controll equivilant. Havnt decided if we want to habcle that here, or not*/
312
+    "\x7F" { /*DEL/BACKSPACE. Need to set bits 9 and 12! return 0x1421;*/ return 0x0000; }
313
+
314
+    /* Rules are processed top to bottom. So All single byte chars MUST be above this line!*/
315
+    [\x20-\x7F] { /*ASCII range*/ return (s[0]<<8) &0xFF00; } /* Should we use yych instead of s[0]?*/
316
+
317
+    /*This is the second half of the ascii exceptions*/
318
+    "\xC3\xA1" { /*LATIN_SMALL_LETTER_A_WITH_ACUTE*/ return 0x2A00; }
319
+    "\xC3\xA9" { /*LATIN_SMALL_LETTER_E_WITH_ACUTE*/ return 0x5C00; }
320
+    "\xC3\xAD" { /*LATIN_SMALL_LETTER_I_WITH_ACUTE*/ return 0x5E00; }
321
+    "\xC3\xB3" { /*LATIN_SMALL_LETTER_O_WITH_ACUTE*/ return 0x5F00; }
322
+    "\xC3\xBA" { /*LATIN_SMALL_LETTER_U_WITH_ACUTE*/ return 0x6000; }
323
+    "\xC3\xA7" { /*LATIN_SMALL_LETTER_C_WITH_CEDILLA*/ return 0x7B00; }
324
+    "\xC3\xB7" { /*DIVISION_SIGN*/ return 0x7C00; }
325
+    "\xC3\x91" { /*LATIN_CAPITAL_LETTER_N_WITH_TILDE*/ return 0x7D00; }
326
+    "\xC3\xB1" { /*LATIN_SMALL_LETTER_N_WITH_TILDE*/ return 0x7E00; }
327
+    "\xE2\x96\x88" { /*FULL_BLOCK*/ return 0x7F00; }
328
+
329
+    /*Special North American character set*/
330
+    "\xC2\xAE" { /*REGISTERED_SIGN*/ return 0x1130; }
331
+    "\xC2\xB0" { /*DEGREE_SIGN*/ return 0x1131; }
332
+    "\xC2\xBD" { /*VULGAR_FRACTION_ONE_HALF*/ return 0x1132; }
333
+    "\xC2\xBF" { /*INVERTED_QUESTION_MARK*/ return 0x1133; }
334
+    "\xE2\x84\xA2" { /*TRADE_MARK_SIGN*/ return 0x1134; }
335
+    "\xC2\xA2" { /*CENT_SIGN*/ return 0x1135; }
336
+    "\xC2\xA3" { /*POUND_SIGN*/ return 0x1136; }
337
+    "\xE2\x99\xAA" { /*EIGHTH_NOTE*/ return 0x1137; }
338
+    "\xC3\xA0" { /*LATIN_SMALL_LETTER_A_WITH_GRAVE*/ return 0x1138; }
339
+    "\xC2\xA0" { /*NO_BREAK_SPACE*/ return 0x1139; }
340
+    "\xC3\xA8" { /*LATIN_SMALL_LETTER_E_WITH_GRAVE*/ return 0x113A; }
341
+    "\xC3\xA2" { /*LATIN_SMALL_LETTER_A_WITH_CIRCUMFLEX*/ return 0x113B; }
342
+    "\xC3\xAA" { /*LATIN_SMALL_LETTER_E_WITH_CIRCUMFLEX*/ return 0x113C; }
343
+    "\xC3\xAE" { /*LATIN_SMALL_LETTER_I_WITH_CIRCUMFLEX*/ return 0x113D; }
344
+    "\xC3\xB4" { /*LATIN_SMALL_LETTER_O_WITH_CIRCUMFLEX*/ return 0x113E; }
345
+    "\xC3\xBB" { /*LATIN_SMALL_LETTER_U_WITH_CIRCUMFLEX*/ return 0x113F; }
346
+
347
+    /*Extended Spanish/Miscellaneous*/
348
+    "\xC3\x81" { /*LATIN_CAPITAL_LETTER_A_WITH_ACUTE*/ return 0x1220; }
349
+    "\xC3\x89" { /*LATIN_CAPITAL_LETTER_E_WITH_ACUTE*/ return 0x1221; }
350
+    "\xC3\x93" { /*LATIN_CAPITAL_LETTER_O_WITH_ACUTE*/ return 0x1222; }
351
+    "\xC3\x9A" { /*LATIN_CAPITAL_LETTER_U_WITH_ACUTE*/ return 0x1223; }
352
+    "\xC3\x9C" { /*LATIN_CAPITAL_LETTER_U_WITH_DIAERESIS*/ return 0x1224; }
353
+    "\xC3\xBC" { /*LATIN_SMALL_LETTER_U_WITH_DIAERESIS*/ return 0x1225; }
354
+    "\xE2\x80\x98" { /*LEFT_SINGLE_QUOTATION_MARK*/ return 0x1226; }
355
+    "\xC2\xA1" { /*INVERTED_EXCLAMATION_MARK*/ return 0x1227; }
356
+    /*ASTERISK handled in ASCII mapping*/
357
+    "\xE2\x80\x99" { /*RIGHT_SINGLE_QUOTATION_MARK -> APOSTROPHE*/ return 0x2700; }
358
+    "\xE2\x80\x94" { /*EM_DASH*/ return 0x122A; }
359
+    "\xC2\xA9" { /*COPYRIGHT_SIGN*/ return 0x122B; }
360
+    "\xE2\x84\xA0" { /*SERVICE_MARK*/ return 0x122C; }
361
+    "\xE2\x80\xA2" { /*BULLET*/ return 0x122D; }
362
+    "\xE2\x80\x9C" { /*LEFT_DOUBLE_QUOTATION_MARK*/ return 0x122E; }
363
+    "\xE2\x80\x9D" { /*RIGHT_DOUBLE_QUOTATION_MARK*/ return 0x122F; }
364
+
365
+    /*Extended French*/
366
+    "\xC3\x80" { /*LATIN_CAPITAL_LETTER_A_WITH_GRAVE*/ return 0x1230; }
367
+    "\xC3\x82" { /*LATIN_CAPITAL_LETTER_A_WITH_CIRCUMFLEX*/ return 0x1231; }
368
+    "\xC3\x87" { /*LATIN_CAPITAL_LETTER_C_WITH_CEDILLA*/ return 0x1232; }
369
+    "\xC3\x88" { /*LATIN_CAPITAL_LETTER_E_WITH_GRAVE*/ return 0x1233; }
370
+    "\xC3\x8A" { /*LATIN_CAPITAL_LETTER_E_WITH_CIRCUMFLEX*/ return 0x1234; }
371
+    "\xC3\x8B" { /*LATIN_CAPITAL_LETTER_E_WITH_DIAERESIS*/ return 0x1235; }
372
+    "\xC3\xAB" { /*LATIN_SMALL_LETTER_E_WITH_DIAERESIS*/ return 0x1236; }
373
+    "\xC3\x8E" { /*LATIN_CAPITAL_LETTER_I_WITH_CIRCUMFLEX*/ return 0x1237; }
374
+    "\xC3\x8F" { /*LATIN_CAPITAL_LETTER_I_WITH_DIAERESIS*/ return 0x1238; }
375
+    "\xC3\xAF" { /*LATIN_SMALL_LETTER_I_WITH_DIAERESIS*/ return 0x1239; }
376
+    "\xC3\x94" { /*LATIN_CAPITAL_LETTER_O_WITH_CIRCUMFLEX*/ return 0x123A; }
377
+    "\xC3\x99" { /*LATIN_CAPITAL_LETTER_U_WITH_GRAVE*/ return 0x123B; }
378
+    "\xC3\xB9" { /*LATIN_SMALL_LETTER_U_WITH_GRAVE*/ return 0x123C; }
379
+    "\xC3\x9B" { /*LATIN_CAPITAL_LETTER_U_WITH_CIRCUMFLEX*/ return 0x123D; }
380
+    "\xC2\xAB" { /*LEFT_POINTING_DOUBLE_ANGLE_QUOTATION_MARK*/ return 0x123E; }
381
+    "\xC2\xBB" { /*RIGHT_POINTING_DOUBLE_ANGLE_QUOTATION_MARK*/ return 0x123F; }
382
+
383
+    /*Portuguese*/
384
+    "\xC3\x83" { /*LATIN_CAPITAL_LETTER_A_WITH_TILDE*/ return 0x1320; }
385
+    "\xC3\xA3" { /*LATIN_SMALL_LETTER_A_WITH_TILDE*/ return 0x1321; }
386
+    "\xC3\x8D" { /*LATIN_CAPITAL_LETTER_I_WITH_ACUTE*/ return 0x1322; }
387
+    "\xC3\x8C" { /*LATIN_CAPITAL_LETTER_I_WITH_GRAVE*/ return 0x1323; }
388
+    "\xC3\xAC" { /*LATIN_SMALL_LETTER_I_WITH_GRAVE*/ return 0x1324; }
389
+    "\xC3\x92" { /*LATIN_CAPITAL_LETTER_O_WITH_GRAVE*/ return 0x1325; }
390
+    "\xC3\xB2" { /*LATIN_SMALL_LETTER_O_WITH_GRAVE*/ return 0x1326; }
391
+    "\xC3\x95" { /*LATIN_CAPITAL_LETTER_O_WITH_TILDE*/ return 0x1327; }
392
+    "\xC3\xB5" { /*LATIN_SMALL_LETTER_O_WITH_TILDE*/ return 0x1328; }
393
+    /*LEFT_CURLY_BRACKET handled in ASCII mapping*/
394
+    /*RIGHT_CURLY_BRACKET handled in ASCII mapping*/
395
+    /*REVERSE_SOLIDUS handled in ASCII mapping*/
396
+    /*CIRCUMFLEX_ACCENT handled in ASCII mapping*/
397
+    /*LOW_LINE handled in ASCII mapping*/
398
+    /*VERTICAL_LINE handled in ASCII mapping*/
399
+    /*TILDE handled in ASCII mapping*/
400
+
401
+    /*German/Danish*/
402
+    "\xC3\x84" { /*LATIN_CAPITAL_LETTER_A_WITH_DIAERESIS*/ return 0x1330; }
403
+    "\xC3\xA4" { /*LATIN_SMALL_LETTER_A_WITH_DIAERESIS*/ return 0x1331; }
404
+    "\xC3\x96" { /*LATIN_CAPITAL_LETTER_O_WITH_DIAERESIS*/ return 0x1332; }
405
+    "\xC3\xB6" { /*LATIN_SMALL_LETTER_O_WITH_DIAERESIS*/ return 0x1333; }
406
+    "\xC3\x9F" { /*LATIN_SMALL_LETTER_SHARP_S*/ return 0x1334; }
407
+    "\xC2\xA5" { /*YEN_SIGN*/ return 0x1335; }
408
+    "\xC2\xA4" { /*CURRENCY_SIGN*/ return 0x1336; }
409
+    "\xC2\xA6" { /*BROKEN_BAR*/ return 0x1337; }
410
+    "\xC3\x85" { /*LATIN_CAPITAL_LETTER_A_WITH_RING_ABOVE*/ return 0x1338; }
411
+    "\xC3\xA5" { /*LATIN_SMALL_LETTER_A_WITH_RING_ABOVE*/ return 0x1339; }
412
+    "\xC3\x98" { /*LATIN_CAPITAL_LETTER_O_WITH_STROKE*/ return 0x133A; }
413
+    "\xC3\xB8" { /*LATIN_SMALL_LETTER_O_WITH_STROKE*/ return 0x133B; }
414
+    "\xE2\x94\x8C" { /*EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_RIGHT*/ return 0x133C; }
415
+    "\xE2\x94\x90" { /*EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_LEFT*/ return 0x133D; }
416
+    "\xE2\x94\x94" { /*EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_RIGHT*/ return 0x133E; }
417
+    "\xE2\x94\x98" { /*EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_LEFT*/ return 0x133F; }
418
+
419
+    /*Default rule*/
420
+    [^] { /*DEFAULT_RULE*/ return 0x0000; }
421
+    */
422
+}
423
obs-studio-0.17.0.tar.xz/deps/libcaption/src/eia608_charmap.c Added
56
 
1
@@ -0,0 +1,54 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#include "eia608_charmap.h"
26
+// 0 - 95: Basic North American character set
27
+// 96 - 111: Special North American character
28
+// 112 - 127: Extended Western European character set : Extended Spanish/Miscellaneous
29
+// 128 - 143: Extended Western European character set : Extended French
30
+// 144 - 159: Extended Western European character set : Portuguese
31
+// 160 - 175: Extended Western European character set : German/Danish
32
+const char* eia608_char_map[] = {
33
+    EIA608_CHAR_SPACE, EIA608_CHAR_EXCLAMATION_MARK, EIA608_CHAR_QUOTATION_MARK, EIA608_CHAR_NUMBER_SIGN, EIA608_CHAR_DOLLAR_SIGN, EIA608_CHAR_PERCENT_SIGN, EIA608_CHAR_AMPERSAND, EIA608_CHAR_RIGHT_SINGLE_QUOTATION_MARK,
34
+    EIA608_CHAR_LEFT_PARENTHESIS, EIA608_CHAR_RIGHT_PARENTHESIS, EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_ACUTE, EIA608_CHAR_PLUS_SIGN, EIA608_CHAR_COMMA, EIA608_CHAR_HYPHEN_MINUS, EIA608_CHAR_FULL_STOP, EIA608_CHAR_SOLIDUS,
35
+    EIA608_CHAR_DIGIT_ZERO, EIA608_CHAR_DIGIT_ONE, EIA608_CHAR_DIGIT_TWO, EIA608_CHAR_DIGIT_THREE, EIA608_CHAR_DIGIT_FOUR, EIA608_CHAR_DIGIT_FIVE, EIA608_CHAR_DIGIT_SIX, EIA608_CHAR_DIGIT_SEVEN, EIA608_CHAR_DIGIT_EIGHT,
36
+    EIA608_CHAR_DIGIT_NINE, EIA608_CHAR_COLON, EIA608_CHAR_SEMICOLON, EIA608_CHAR_LESS_THAN_SIGN, EIA608_CHAR_EQUALS_SIGN, EIA608_CHAR_GREATER_THAN_SIGN, EIA608_CHAR_QUESTION_MARK, EIA608_CHAR_COMMERCIAL_AT,
37
+    EIA608_CHAR_LATIN_CAPITAL_LETTER_A, EIA608_CHAR_LATIN_CAPITAL_LETTER_B, EIA608_CHAR_LATIN_CAPITAL_LETTER_C, EIA608_CHAR_LATIN_CAPITAL_LETTER_D, EIA608_CHAR_LATIN_CAPITAL_LETTER_E, EIA608_CHAR_LATIN_CAPITAL_LETTER_F, EIA608_CHAR_LATIN_CAPITAL_LETTER_G, EIA608_CHAR_LATIN_CAPITAL_LETTER_H,
38
+    EIA608_CHAR_LATIN_CAPITAL_LETTER_I, EIA608_CHAR_LATIN_CAPITAL_LETTER_J, EIA608_CHAR_LATIN_CAPITAL_LETTER_K, EIA608_CHAR_LATIN_CAPITAL_LETTER_L, EIA608_CHAR_LATIN_CAPITAL_LETTER_M, EIA608_CHAR_LATIN_CAPITAL_LETTER_N, EIA608_CHAR_LATIN_CAPITAL_LETTER_O, EIA608_CHAR_LATIN_CAPITAL_LETTER_P,
39
+    EIA608_CHAR_LATIN_CAPITAL_LETTER_Q, EIA608_CHAR_LATIN_CAPITAL_LETTER_R, EIA608_CHAR_LATIN_CAPITAL_LETTER_S, EIA608_CHAR_LATIN_CAPITAL_LETTER_T, EIA608_CHAR_LATIN_CAPITAL_LETTER_U, EIA608_CHAR_LATIN_CAPITAL_LETTER_V, EIA608_CHAR_LATIN_CAPITAL_LETTER_W, EIA608_CHAR_LATIN_CAPITAL_LETTER_X,
40
+    EIA608_CHAR_LATIN_CAPITAL_LETTER_Y, EIA608_CHAR_LATIN_CAPITAL_LETTER_Z, EIA608_CHAR_LEFT_SQUARE_BRACKET, EIA608_CHAR_LATIN_SMALL_LETTER_E_WITH_ACUTE, EIA608_CHAR_RIGHT_SQUARE_BRACKET, EIA608_CHAR_LATIN_SMALL_LETTER_I_WITH_ACUTE, EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_ACUTE,
41
+    EIA608_CHAR_LATIN_SMALL_LETTER_U_WITH_ACUTE, EIA608_CHAR_LATIN_SMALL_LETTER_A, EIA608_CHAR_LATIN_SMALL_LETTER_B, EIA608_CHAR_LATIN_SMALL_LETTER_C, EIA608_CHAR_LATIN_SMALL_LETTER_D, EIA608_CHAR_LATIN_SMALL_LETTER_E, EIA608_CHAR_LATIN_SMALL_LETTER_F, EIA608_CHAR_LATIN_SMALL_LETTER_G, EIA608_CHAR_LATIN_SMALL_LETTER_H,
42
+    EIA608_CHAR_LATIN_SMALL_LETTER_I, EIA608_CHAR_LATIN_SMALL_LETTER_J, EIA608_CHAR_LATIN_SMALL_LETTER_K, EIA608_CHAR_LATIN_SMALL_LETTER_L, EIA608_CHAR_LATIN_SMALL_LETTER_M, EIA608_CHAR_LATIN_SMALL_LETTER_N, EIA608_CHAR_LATIN_SMALL_LETTER_O, EIA608_CHAR_LATIN_SMALL_LETTER_P,
43
+    EIA608_CHAR_LATIN_SMALL_LETTER_Q, EIA608_CHAR_LATIN_SMALL_LETTER_R, EIA608_CHAR_LATIN_SMALL_LETTER_S, EIA608_CHAR_LATIN_SMALL_LETTER_T, EIA608_CHAR_LATIN_SMALL_LETTER_U, EIA608_CHAR_LATIN_SMALL_LETTER_V, EIA608_CHAR_LATIN_SMALL_LETTER_W, EIA608_CHAR_LATIN_SMALL_LETTER_X,
44
+    EIA608_CHAR_LATIN_SMALL_LETTER_Y, EIA608_CHAR_LATIN_SMALL_LETTER_Z, EIA608_CHAR_LATIN_SMALL_LETTER_C_WITH_CEDILLA, EIA608_CHAR_DIVISION_SIGN, EIA608_CHAR_LATIN_CAPITAL_LETTER_N_WITH_TILDE, EIA608_CHAR_LATIN_SMALL_LETTER_N_WITH_TILDE, EIA608_CHAR_FULL_BLOCK,
45
+    EIA608_CHAR_REGISTERED_SIGN, EIA608_CHAR_DEGREE_SIGN, EIA608_CHAR_VULGAR_FRACTION_ONE_HALF, EIA608_CHAR_INVERTED_QUESTION_MARK, EIA608_CHAR_TRADE_MARK_SIGN, EIA608_CHAR_CENT_SIGN, EIA608_CHAR_POUND_SIGN, EIA608_CHAR_EIGHTH_NOTE,
46
+    EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_GRAVE, EIA608_CHAR_NO_BREAK_SPACE, EIA608_CHAR_LATIN_SMALL_LETTER_E_WITH_GRAVE, EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_CIRCUMFLEX, EIA608_CHAR_LATIN_SMALL_LETTER_E_WITH_CIRCUMFLEX, EIA608_CHAR_LATIN_SMALL_LETTER_I_WITH_CIRCUMFLEX, EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_CIRCUMFLEX, EIA608_CHAR_LATIN_SMALL_LETTER_U_WITH_CIRCUMFLEX,
47
+    EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_ACUTE, EIA608_CHAR_LATIN_CAPITAL_LETTER_E_WITH_ACUTE, EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_ACUTE, EIA608_CHAR_LATIN_CAPITAL_LETTER_U_WITH_ACUTE, EIA608_CHAR_LATIN_CAPITAL_LETTER_U_WITH_DIAERESIS, EIA608_CHAR_LATIN_SMALL_LETTER_U_WITH_DIAERESIS, EIA608_CHAR_LEFT_SINGLE_QUOTATION_MARK, EIA608_CHAR_INVERTED_EXCLAMATION_MARK,
48
+    EIA608_CHAR_ASTERISK, EIA608_CHAR_APOSTROPHE, EIA608_CHAR_EM_DASH, EIA608_CHAR_COPYRIGHT_SIGN, EIA608_CHAR_SERVICE_MARK, EIA608_CHAR_BULLET, EIA608_CHAR_LEFT_DOUBLE_QUOTATION_MARK, EIA608_CHAR_RIGHT_DOUBLE_QUOTATION_MARK,
49
+    EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_GRAVE, EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_CIRCUMFLEX, EIA608_CHAR_LATIN_CAPITAL_LETTER_C_WITH_CEDILLA, EIA608_CHAR_LATIN_CAPITAL_LETTER_E_WITH_GRAVE, EIA608_CHAR_LATIN_CAPITAL_LETTER_E_WITH_CIRCUMFLEX, EIA608_CHAR_LATIN_CAPITAL_LETTER_E_WITH_DIAERESIS, EIA608_CHAR_LATIN_SMALL_LETTER_E_WITH_DIAERESIS, EIA608_CHAR_LATIN_CAPITAL_LETTER_I_WITH_CIRCUMFLEX,
50
+    EIA608_CHAR_LATIN_CAPITAL_LETTER_I_WITH_DIAERESIS, EIA608_CHAR_LATIN_SMALL_LETTER_I_WITH_DIAERESIS, EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_CIRCUMFLEX, EIA608_CHAR_LATIN_CAPITAL_LETTER_U_WITH_GRAVE, EIA608_CHAR_LATIN_SMALL_LETTER_U_WITH_GRAVE, EIA608_CHAR_LATIN_CAPITAL_LETTER_U_WITH_CIRCUMFLEX, EIA608_CHAR_LEFT_POINTING_DOUBLE_ANGLE_QUOTATION_MARK, EIA608_CHAR_RIGHT_POINTING_DOUBLE_ANGLE_QUOTATION_MARK,
51
+    EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_TILDE, EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_TILDE, EIA608_CHAR_LATIN_CAPITAL_LETTER_I_WITH_ACUTE, EIA608_CHAR_LATIN_CAPITAL_LETTER_I_WITH_GRAVE, EIA608_CHAR_LATIN_SMALL_LETTER_I_WITH_GRAVE, EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_GRAVE, EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_GRAVE, EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_TILDE,
52
+    EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_TILDE, EIA608_CHAR_LEFT_CURLY_BRACKET, EIA608_CHAR_RIGHT_CURLY_BRACKET, EIA608_CHAR_REVERSE_SOLIDUS, EIA608_CHAR_CIRCUMFLEX_ACCENT, EIA608_CHAR_LOW_LINE, EIA608_CHAR_VERTICAL_LINE, EIA608_CHAR_TILDE,
53
+    EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_DIAERESIS, EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_DIAERESIS, EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_DIAERESIS, EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_DIAERESIS, EIA608_CHAR_LATIN_SMALL_LETTER_SHARP_S, EIA608_CHAR_YEN_SIGN, EIA608_CHAR_CURRENCY_SIGN, EIA608_CHAR_BROKEN_BAR,
54
+    EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_RING_ABOVE, EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_RING_ABOVE, EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_STROKE, EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_STROKE, EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_RIGHT, EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_LEFT, EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_RIGHT, EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_LEFT,
55
+};
56
obs-studio-0.17.0.tar.xz/deps/libcaption/src/scc.c Added
56
 
1
@@ -0,0 +1,54 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#include "scc.h"
26
+#include "utf8.h"
27
+#include <stdio.h>
28
+#include <string.h>
29
+#include <stdlib.h>
30
+
31
+#define FRAME_RATE (1000.0/30)
32
+#define SCCTIME2MS(HH,MM,SS,FF) (((HH*3600.0 + MM*60.0 + SS) * 1000.0) + ( FF * FRAME_RATE ))
33
+
34
+// 00:00:25:16  9420 9440 aeae ae79 ef75 2068 6176 e520 79ef 75f2 20f2 ef62 eff4 e9e3 732c 2061 6e64 2049 94fe 9723 ea75 73f4 20f7 616e f420 f4ef 2062 e520 61f7 e573 ef6d e520 e96e 2073 7061 e3e5 ae80 942c 8080 8080 942f
35
+
36
+int scc_to_608 (const char* line, double* pts, uint16_t* cc, int cc_max)
37
+{
38
+    int cc_count = 0, cc_data = 0, hh = 0, mm = 0, ss = 0, ff = 0;
39
+
40
+    // TODO if ';' use 29.79 fps, if ':' use 30 fls
41
+    if (4 == sscanf (line, "%2d:%2d:%2d%*1[:;]%2d", &hh, &mm, &ss, &ff)) {
42
+        (*pts) = SCCTIME2MS (hh,mm,ss,ff); // scc files start at one hour for some reason
43
+        line += 12;
44
+
45
+        while (1 == sscanf (line, "%04x ", &cc_data)) {
46
+            line += 5; cc[cc_count] = cc_data; ++cc_count;
47
+
48
+            if (cc_count >= cc_max) {
49
+                break;
50
+            }
51
+        }
52
+    }
53
+
54
+    return cc_count;
55
+}
56
obs-studio-0.17.0.tar.xz/deps/libcaption/src/srt.c Added
196
 
1
@@ -0,0 +1,194 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+#include "srt.h"
26
+#include "utf8.h"
27
+#include <stdio.h>
28
+#include <string.h>
29
+#include <stdlib.h>
30
+
31
+
32
+
33
+srt_t* srt_new (const utf8_char_t* data, size_t size, double timestamp, srt_t* prev, srt_t** head)
34
+{
35
+    srt_t* srt = malloc (sizeof (srt_t)+size+1);
36
+    srt->next = 0;
37
+    srt->duration = 0;
38
+    srt->aloc = size;
39
+    srt->timestamp = timestamp;
40
+    utf8_char_t* dest = (utf8_char_t*) srt_data (srt);
41
+
42
+    if (prev) {
43
+        prev->next = srt;
44
+        prev->duration = timestamp - prev->timestamp;
45
+    }
46
+
47
+    if (head && 0 == (*head)) {
48
+        (*head) = srt;
49
+    }
50
+
51
+    if (data) {
52
+        memcpy (dest, data, size);
53
+    } else {
54
+        memset (dest, 0, size);
55
+    }
56
+
57
+    dest[size] = '\0';
58
+    return srt;
59
+}
60
+
61
+srt_t* srt_free_head (srt_t* head)
62
+{
63
+    srt_t* next = head->next;
64
+    free (head);
65
+    return next;
66
+}
67
+
68
+void srt_free (srt_t* srt)
69
+{
70
+    while (srt) {
71
+        srt = srt_free_head (srt);
72
+    }
73
+}
74
+
75
+#define SRTTIME2SECONDS(HH,MM,SS,MS) ((HH*3600.0) + (MM*60.0) + SS + (MS/1000.0))
76
+srt_t* srt_parse (const utf8_char_t* data, size_t size)
77
+{
78
+    int counter;
79
+    srt_t* head = 0, *prev = 0;
80
+    double str_pts = 0, end_pts = 0;
81
+    size_t line_length = 0, trimmed_length = 0;
82
+    int hh1, hh2, mm1, mm2, ss1, ss2, ms1, ms2;
83
+
84
+    for (;;) {
85
+        line_length = 0;
86
+
87
+        do {
88
+            data += line_length;
89
+            size -= line_length;
90
+            line_length = utf8_line_length (data);
91
+            trimmed_length = utf8_trimmed_length (data,line_length);
92
+            // Skip empty lines
93
+        } while (0 < line_length && 0 == trimmed_length);
94
+
95
+        // linelength cant be zero before EOF
96
+        if (0 == line_length) {
97
+            break;
98
+        }
99
+
100
+        counter = atoi (data);
101
+        // printf ("counter (%d): '%.*s'\n", line_length, (int) line_length, data);
102
+        data += line_length;
103
+        size -= line_length;
104
+
105
+        line_length = utf8_line_length (data);
106
+        // printf ("time (%d): '%.*s'\n", line_length, (int) line_length, data);
107
+
108
+        {
109
+            if (8 == sscanf (data, "%d:%2d:%2d%*1[,.]%3d --> %d:%2d:%2d%*1[,.]%3d", &hh1, &mm1, &ss1, &ms1, &hh2, &mm2, &ss2, &ms2)) {
110
+                str_pts = SRTTIME2SECONDS (hh1, mm1, ss1, ms1);
111
+                end_pts = SRTTIME2SECONDS (hh2, mm2, ss2, ms2);
112
+            }
113
+
114
+            data += line_length;
115
+            size -= line_length;
116
+        }
117
+
118
+        // Caption text starts here
119
+        const utf8_char_t* text = data;
120
+        size_t text_size = 0;
121
+        // printf ("time: '(%f --> %f)\n",srt.srt_time, srt.end_time);
122
+
123
+        do {
124
+            line_length = utf8_line_length (data);
125
+            trimmed_length = utf8_trimmed_length (data,line_length);
126
+            // printf ("cap (%d): '%.*s'\n", line_length, (int) trimmed_length, data);
127
+            data += line_length;
128
+            size -= line_length;
129
+            text_size += line_length;
130
+        } while (trimmed_length);
131
+
132
+        // should we trim here?
133
+        srt_t* srt = srt_new (text,text_size,str_pts,prev,&head);
134
+        srt->duration = end_pts - str_pts;
135
+        prev = srt;
136
+    }
137
+
138
+    return head;
139
+}
140
+
141
+int srt_to_caption_frame (srt_t* srt, caption_frame_t* frame)
142
+{
143
+    const char* data = srt_data (srt);
144
+    return caption_frame_from_text (frame,data);
145
+}
146
+
147
+srt_t* srt_from_caption_frame (caption_frame_t* frame, srt_t* prev, srt_t** head)
148
+{
149
+    // CRLF per row, plus an extra at the end
150
+    srt_t* srt = srt_new (0, 2+CAPTION_FRAME_TEXT_BYTES, frame->timestamp, prev, head);
151
+    utf8_char_t* data = srt_data (srt);
152
+
153
+    caption_frame_to_text (frame,data);
154
+    // srt requires an extra new line
155
+    strcat ( (char*) data,"\r\n");
156
+
157
+    return srt;
158
+}
159
+
160
+static inline void _crack_time (double tt, int* hh, int* mm, int* ss, int* ms)
161
+{
162
+    (*ms) = (int) ((int64_t) (tt * 1000.0) % 1000);
163
+    (*ss) = (int) ((int64_t) (tt) % 60);
164
+    (*mm) = (int) ((int64_t) (tt / (60.0)) % 60);
165
+    (*hh) = (int) ((int64_t) (tt / (60.0*60.0)));
166
+}
167
+
168
+static void _dump (srt_t* head, char type)
169
+{
170
+    int i;
171
+    srt_t* srt;
172
+
173
+    if ('v' == type) {
174
+        printf ("WEBVTT\r\n");
175
+    }
176
+
177
+    for (srt = head, i = 1; srt; srt=srt_next (srt), ++i) {
178
+        int hh1, hh2, mm1, mm2, ss1, ss2, ms1, ms2;
179
+        _crack_time (srt->timestamp, &hh1, &mm1, &ss1, &ms1);
180
+        _crack_time (srt->timestamp + srt->duration, &hh2, &mm2, &ss2, &ms2);
181
+
182
+        if ('s' == type) {
183
+            printf ("%02d\r\n%d:%02d:%02d,%03d --> %02d:%02d:%02d,%03d\r\n%s\r\n", i,
184
+                    hh1, mm1, ss1, ms1, hh2, mm2, ss2, ms2, srt_data (srt));
185
+        }
186
+
187
+        else if ('v' == type) {
188
+            printf ("%d:%02d:%02d.%03d --> %02d:%02d:%02d.%03d\r\n%s\r\n",
189
+                    hh1, mm1, ss1, ms1, hh2, mm2, ss2, ms2, srt_data (srt));
190
+        }
191
+    }
192
+}
193
+
194
+void srt_dump (srt_t* head) { _dump (head,'s'); }
195
+void vtt_dump (srt_t* head) { _dump (head,'v'); }
196
obs-studio-0.17.0.tar.xz/deps/libcaption/src/utf8.c Added
172
 
1
@@ -0,0 +1,170 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+
26
+
27
+
28
+#include "utf8.h"
29
+#include <string.h>
30
+
31
+const utf8_char_t* utf8_char_next (const char* s)
32
+{
33
+    if (0x80 == (s[0]&0xC0)) { ++s; }
34
+
35
+    return s;
36
+}
37
+
38
+// returnes the length of the char in bytes
39
+size_t utf8_char_length (const utf8_char_t* c)
40
+{
41
+    // count null term as zero size
42
+    if (0x00 == c[0]) { return 0; }
43
+
44
+    if (0x00 == (c[0]&0x80)) { return 1; }
45
+
46
+    if (0xC0 == (c[0]&0xE0) && 0x80 == (c[1]&0xC0)) { return 2; }
47
+
48
+    if (0xE0 == (c[0]&0xF0) && 0x80 == (c[1]&0xC0) && 0x80 == (c[2]&0xC0)) { return 3; }
49
+
50
+    if (0xF0 == (c[0]&0xF8) && 0x80 == (c[1]&0xC0) && 0x80 == (c[2]&0xC0) && 0x80 == (c[3]&0xC0)) { return 4; }
51
+
52
+    return 0;
53
+}
54
+
55
+// returns length of the string in bytes
56
+// size is number of charcter to count (0 to count until NULL term)
57
+size_t utf8_string_length (const utf8_char_t* data, utf8_size_t size)
58
+{
59
+    size_t char_length, byts = 0;
60
+
61
+    if (0 == size) {
62
+        size = utf8_char_count (data,0);
63
+    }
64
+
65
+    for (; 0 < size ; --size) {
66
+        if (0 == (char_length = utf8_char_length (data))) {
67
+            break;
68
+        }
69
+
70
+        data += char_length;
71
+        byts += char_length;
72
+    }
73
+
74
+    return byts;
75
+}
76
+
77
+size_t utf8_char_copy (utf8_char_t* dst, const utf8_char_t* src)
78
+{
79
+    size_t bytes = utf8_char_length (src);
80
+
81
+    if (bytes&&dst) {
82
+        memcpy (dst,src,bytes);
83
+        dst[bytes] = '\0';
84
+    }
85
+
86
+    return bytes;
87
+}
88
+
89
+// returnes the number of utf8 charcters in a string given the number of bytes
90
+// to count until the a null terminator, pass 0 for size
91
+utf8_size_t utf8_char_count (const char* data, size_t size)
92
+{
93
+    size_t i, bytes = 0;
94
+    utf8_size_t count = 0;
95
+
96
+    if (0 == size) {
97
+        size = strlen (data);
98
+    }
99
+
100
+    for (i = 0 ; i < size ; ++count, i += bytes) {
101
+        if (0 == (bytes = utf8_char_length (&data[i]))) {
102
+            break;
103
+        }
104
+    }
105
+
106
+    return count;
107
+}
108
+
109
+// returnes the length of the line in bytes triming not printable charcters at the end
110
+size_t utf8_trimmed_length (const char* data, size_t size)
111
+{
112
+    for (; 0 < size && ' ' >= (uint8_t) data[size-1] ; --size) { }
113
+
114
+    return size;
115
+}
116
+
117
+// returns the length in bytes of the line including the new line charcter(s)
118
+// auto detects between windows(CRLF), unix(LF), mac(CR) and riscos (LFCR) line endings
119
+size_t utf8_line_length (const char* data)
120
+{
121
+    size_t len = 0;
122
+
123
+    for (len = 0; 0 != data[len]; ++len) {
124
+        if ('\r' == data[len]) {
125
+            if ('\n' == data[len+1]) {
126
+                return len + 2; // windows
127
+            } else {
128
+                return len + 1; // unix
129
+            }
130
+        } else if ('\n' == data[len]) {
131
+            if ('\r' == data[len+1]) {
132
+                return len + 2; // riscos
133
+            } else {
134
+                return len + 1; // macos
135
+            }
136
+        }
137
+    }
138
+
139
+    return len;
140
+}
141
+
142
+// returns number of chars to include before split
143
+utf8_size_t utf8_wrap_length (const utf8_char_t* data, utf8_size_t size)
144
+{
145
+    // Set split_at to size, so if a split point cna not be found, retuns the size passed in
146
+    size_t char_length, char_count, split_at = size;
147
+
148
+    for (char_count = 0 ; char_count <= size ; ++char_count) {
149
+        if (' ' >= (*data)) {
150
+            split_at = char_count;
151
+        }
152
+
153
+        char_length = utf8_char_length (data);
154
+        data += char_length;
155
+    }
156
+
157
+    return split_at;
158
+}
159
+
160
+int utf8_line_count (const utf8_char_t* data)
161
+{
162
+    size_t len = 0;
163
+    int count = 0;
164
+
165
+    do {
166
+        len = utf8_line_length (data);
167
+        data += len; ++count;
168
+    } while (0<len);
169
+
170
+    return count-1;
171
+}
172
obs-studio-0.17.0.tar.xz/deps/libcaption/src/xds.c Added
53
 
1
@@ -0,0 +1,51 @@
2
+/**********************************************************************************************/
3
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
4
+/*                                                                                            */
5
+/* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file  */
6
+/* except in compliance with the License. A copy of the License is located at                 */
7
+/*                                                                                            */
8
+/*     http://aws.amazon.com/apache2.0/                                                       */
9
+/*                                                                                            */
10
+/* or in the "license" file accompanying this file. This file is distributed on an "AS IS"    */
11
+/* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the    */
12
+/* License for the specific language governing permissions and limitations under the License. */
13
+/**********************************************************************************************/
14
+// http://www.theneitherworld.com/mcpoodle/SCC_TOOLS/DOCS/CC_XDS.HTML#PR
15
+#include "xds.h"
16
+#include "caption.h"
17
+#include <string.h>
18
+
19
+void xds_init (xds_t* xds)
20
+{
21
+    memset (xds,0,sizeof (xds_t));
22
+}
23
+
24
+int xds_decode (xds_t* xds, uint16_t cc)
25
+{
26
+    switch (xds->state) {
27
+    default:
28
+    case 0:
29
+        xds_init (xds);
30
+        xds->class = (cc&0x0F00) >>8;
31
+        xds->type = (cc&0x000F);
32
+        xds->state = 1;
33
+        return LIBCAPTION_OK;
34
+
35
+    case 1:
36
+        if (0x8F00 == (cc&0xFF00)) {
37
+            xds->checksum = (cc&0x007F);
38
+            xds->state = 0;
39
+            return LIBCAPTION_READY;
40
+        }
41
+
42
+        if (xds->size < 32) {
43
+            xds->content[xds->size+0] = (cc&0x7F00) >>8;
44
+            xds->content[xds->size+1] = (cc&0x007F);
45
+            xds->size += 2;
46
+            return LIBCAPTION_OK;
47
+        }
48
+    }
49
+
50
+    xds->state = 0;
51
+    return LIBCAPTION_ERROR;
52
+}
53
obs-studio-0.17.0.tar.xz/deps/libcaption/unit_tests Added
2
 
1
+(directory)
2
obs-studio-0.17.0.tar.xz/deps/libcaption/unit_tests/eia608_test.c Added
282
 
1
@@ -0,0 +1,280 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+
26
+#include "eia608.h"
27
+#include <stdio.h>
28
+#include <stdlib.h>
29
+#include <time.h>
30
+#include <unistd.h>
31
+// all possible utf8 valies, including invalid ones
32
+void encode_utf8ish (int32_t in, char out[7])
33
+{
34
+    if (0 > in) {
35
+        out[0] = 0;
36
+        return;
37
+    }
38
+
39
+    // 0xxxxxxx, 7 bits
40
+    if (0x80 > in) {
41
+        out[0] = in;
42
+        out[1] = 0;
43
+        return;
44
+    }
45
+
46
+    // 110xxxxx   10xxxxxx, 11 bits
47
+    if (0x800 > in) {
48
+        out[0] = 0xC0 | ( (in >> (6*1)) & 0x1F);
49
+        out[1] = 0x80 | ( (in >> (6*0)) & 0x3F);
50
+        out[2] = 0;
51
+        return;
52
+    }
53
+
54
+    // 1110xxxx   10xxxxxx    10xxxxxx, 16 bits
55
+    if (0x10000 > in) {
56
+        out[0] = 0xE0 | ( (in >> (6*2)) & 0x0F);
57
+        out[1] = 0x80 | ( (in >> (6*1)) & 0x3F);
58
+        out[2] = 0x80 | ( (in >> (6*0)) & 0x3F);
59
+        out[3] = 0;
60
+        return;
61
+    }
62
+
63
+    // 11110xxx   10xxxxxx    10xxxxxx    10xxxxxx, 21 bits
64
+    if (0x200000 > in) {
65
+        out[0] = 0xF0 | ( (in >> (6*3)) & 0x07);
66
+        out[1] = 0x80 | ( (in >> (6*2)) & 0x3F);
67
+        out[2] = 0x80 | ( (in >> (6*1)) & 0x3F);
68
+        out[3] = 0x80 | ( (in >> (6*0)) & 0x3F);
69
+        out[4] = 0;
70
+        return;
71
+    }
72
+
73
+    // 111110xx   10xxxxxx    10xxxxxx    10xxxxxx    10xxxxxx, 26 bits
74
+    if (0x4000000 > in) {
75
+        out[0] = 0xF8 | ( (in >> (6*4)) & 0x03);
76
+        out[1] = 0x80 | ( (in >> (6*3)) & 0x3F);
77
+        out[2] = 0x80 | ( (in >> (6*2)) & 0x3F);
78
+        out[3] = 0x80 | ( (in >> (6*1)) & 0x3F);
79
+        out[4] = 0x80 | ( (in >> (6*0)) & 0x3F);
80
+        out[5] = 0;
81
+        return;
82
+    }
83
+
84
+    // 1111110x   10xxxxxx    10xxxxxx    10xxxxxx    10xxxxxx    10xxxxxx, 31 bits
85
+    if (0x80000000 > in) {
86
+        out[0] = 0xFC | ( (in >> (6*5)) & 0x01);
87
+        out[1] = 0x80 | ( (in >> (6*4)) & 0x3F);
88
+        out[2] = 0x80 | ( (in >> (6*3)) & 0x3F);
89
+        out[3] = 0x80 | ( (in >> (6*2)) & 0x3F);
90
+        out[4] = 0x80 | ( (in >> (6*1)) & 0x3F);
91
+        out[5] = 0x80 | ( (in >> (6*0)) & 0x3F);
92
+        out[6] = 0;
93
+        return;
94
+    }
95
+}
96
+
97
+void test_all_utf8()
98
+{
99
+    char s[7]; size_t size, count = 0; uint16_t code1, code2;
100
+
101
+    for (int i = 0 ; i < 0x80000000 ; ++i) {
102
+        encode_utf8ish (i, &s[0]);
103
+        code1 = eia608_from_utf8 ( (const char*) &s[0], 0, &size);
104
+
105
+        // code2 = eia608_from_utf8 ( (const char*) &s[0], 1, &size);
106
+        if (code1) {
107
+            ++count;
108
+            printf ("%d: string: '%s' code: %04X\n",count, &s[0],code1);
109
+        }
110
+    }
111
+
112
+    // Count must be 177
113
+    // 176 charcters, pile we have two mapping for left quote mark
114
+}
115
+
116
+#define BIN "%d%d%d%d%d%d%d%d %d%d%d%d%d%d%d%d"
117
+#define BIND(D) ((D)>>15)&0x01, ((D)>>14)&0x01,((D)>>13)&0x01,((D)>>12)&0x01,((D)>>11)&0x01,((D)>>10)&0x01,((D)>>9)&0x01,((D)>>8)&0x01,((D)>>7)&0x01,((D)>>6)&0x01,((D)>>5)&0x01,((D)>>4)&0x01,((D)>>3)&0x01,((D)>>2)&0x01,((D)>>1)&0x01,((D)>>0)&0x01
118
+
119
+
120
+void print_bin (int n)
121
+{
122
+    int mask = 0x80;
123
+
124
+    for (int mask = 0x80 ; mask ; mask >>= 1) {
125
+        printf ("%s", n & mask ? "1" : "0");
126
+    }
127
+
128
+    printf ("\n");
129
+}
130
+
131
+void void_test_all_possible_code_words()
132
+{
133
+    for (int i = 0 ; i <= 0x3FFF ; ++i) {
134
+        int16_t code = eia608_parity ( ( (i<<1) &0x7F00) | (i&0x7F));
135
+
136
+        int count =eia608_cc_data_is_extended_data_service (code)+
137
+                   eia608_cc_data_is_basic_north_american_character (code) +
138
+                   eia608_cc_data_is_special_north_american_character (code) +
139
+                   eia608_cc_data_is_extended_western_european_character (code) +
140
+                   eia608_cc_data_is_nonwestern_norpak_character (code) +
141
+                   eia608_cc_data_is_row_preamble (code) +
142
+                   eia608_cc_data_is_control_command (code);
143
+
144
+        if (1 < count) {
145
+            printf ("code 0x%04X matched >1\n",code&0x7F7F);
146
+        }
147
+
148
+        // if (0 == count) {
149
+        //     printf ("code 0x%04X not matched %d\n",eia608_strip_parity_bits (code), i);
150
+        // }
151
+    }
152
+}
153
+
154
+void print_charmap()
155
+{
156
+    for (int i = 0 ; i < EIA608_CHAR_COUNT ; ++i) {
157
+        printf ("%s", eia608_char_map[i]);
158
+    }
159
+
160
+    printf ("\n");
161
+}
162
+
163
+void dance()
164
+{
165
+    for (int i = 0 ; i < 100 ; ++i) {
166
+        const char* l = 0 == rand() % 2 ? EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_RIGHT : EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_RIGHT;
167
+        const char* r = 0 == rand() % 2 ? EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_LEFT : EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_LEFT;
168
+        printf ("%s %s%s%s%s%s%s%s %s ", EIA608_CHAR_EIGHTH_NOTE, l, EIA608_CHAR_LEFT_PARENTHESIS, EIA608_CHAR_EM_DASH, EIA608_CHAR_LOW_LINE, EIA608_CHAR_EM_DASH,
169
+                EIA608_CHAR_RIGHT_PARENTHESIS, r, EIA608_CHAR_EIGHTH_NOTE);
170
+    }
171
+
172
+}
173
+
174
+
175
+int main (int argc, const char** arg)
176
+{
177
+    // print_charmap();
178
+    // // return 0;
179
+    // srand (time (0));
180
+    // // test_all_utf8();
181
+    // // void_test_all_possible_code_words();
182
+    // // return 0;
183
+    // // print_charmap();
184
+    // dance();
185
+    // return 0;
186
+    for (int i = 0 ; i <= 0x3FFF ; ++i) {
187
+        uint16_t code1 = eia608_parity ( ( (i<<1) &0x7F00) | (i&0x7F));
188
+
189
+        switch (eia608_cc_data_type (code1)) {
190
+        default:
191
+        case EIA608_CC_DATA_UNKNOWN:
192
+            // printf ("Unknown code %04X\n",code);
193
+            break;
194
+
195
+        case EIA608_CC_DATA_CONTROL_COMMAND: {
196
+            int cc;
197
+            eia608_control_t cmd = eia608_parse_control (code1, &cc);
198
+            uint16_t code2 = eia608_control_command (cmd,cc);
199
+
200
+            if (code1 != code2) {
201
+                printf (BIN " != " BIN " (0x%04x != 0x%04x) cc: %d\n", BIND (code1), BIND (code2),code1,code2,cc);
202
+            }
203
+        } break;
204
+
205
+
206
+        case EIA608_CC_DATA_BASIC_NORTH_AMERICAN_CHARACTER: {
207
+            char char1[5], char2[5]; int chan; size_t size;
208
+
209
+            if (eia608_to_utf8 (code1, &chan, &char1[0], &char2[0])) {
210
+                uint16_t code2 = eia608_from_utf8_2 (&char1[0], &char2[0]);
211
+
212
+                // if the second char is invalid, mask it off, we will accept the first
213
+                if (0x80 < (code1 &0x007F) || 0x20 > (code1 &0x007F)) {
214
+                    code1 = (code1&0xFF00) |0x0080;
215
+                }
216
+
217
+                if (code1 == code2) {
218
+                    // printf ("%s " BIN " == " BIN " (0x%04x == 0x%04x)\n", &char1[0], BIND (code1), BIND (code2),code1,code2);
219
+                } else {
220
+                    printf ("%s %s " BIN " != " BIN " (0x%04x != 0x%04x)\n", &char1[0], &char2[0], BIND (code1), BIND (code2),code1,code2);
221
+                }
222
+            }
223
+
224
+        } break;
225
+
226
+        case EIA608_CC_DATA_SPECIAL_NORTH_AMERICAN_CHARACTER:
227
+        case EIA608_CC_DATA_EXTENDED_WESTERN_EUROPEAN_CHARACTER: {
228
+            char char1[5], char2[5]; int chan; size_t size;
229
+
230
+            if (eia608_to_utf8 (code1, &chan, &char1[0], &char2[0])) {
231
+                uint16_t code2 = eia608_from_utf8 (&char1[0], chan, &size);
232
+
233
+                if (code1 == code2) {
234
+                    // printf ("%s " BIN " == " BIN " (0x%04x == 0x%04x)\n", &char1[0], BIND (code1), BIND (code2),code1,code2);
235
+                } else {
236
+                    printf ("%s " BIN " != " BIN " (0x%04x != 0x%04x)\n", &char1[0], BIND (code1), BIND (code2),code1,code2);
237
+                }
238
+            }
239
+        } break;
240
+
241
+            // #define EIA608_CODE_ROW_PREAMBLE                        4
242
+            // #define EIA608_CODE_EXTENDED_DATA_SERVICE               5
243
+            // #define EIA608_CODE_CONTROL_COMMAND                     6
244
+        }
245
+    }
246
+
247
+    return 0;
248
+}
249
+
250
+
251
+
252
+
253
+//     for (uint16_t i  = 0 ; i < 0x4000; ++i) {
254
+//         int chan;
255
+//         char str[7];
256
+//         uint16_t code = ( (i<<1) &0x7F00) | (i & 0x007F);
257
+//
258
+//         if (eia608_to_utf8 (code,&chan,str)) {
259
+//             printf ("code: 0x%04X  str: '%s'\n", code,str);
260
+//         }
261
+//     }
262
+//
263
+//     // for(int i = 0 ; i < cie608_char_count ; ++i)
264
+//     // {
265
+//     //     cie608_char_map[i]
266
+//     //
267
+//     // }
268
+//
269
+//
270
+//     for (int i = 0 ; i < 128 ; ++i) {
271
+//         // print_bin( B7( i ) );
272
+//         // print_bin( eia608_parity_table[i] );
273
+//         printf ("%d  %d %d\n", i, 0x7F & eia608_parity_table[i], eia608_parity_table[i]);
274
+//         // if ( i != eia608_parity_table[i] )
275
+//         // {
276
+//         //   printf( "ERROR\n" );
277
+//         //
278
+//         // }
279
+//     }
280
+//
281
+// }
282
obs-studio-0.17.0.tar.xz/deps/libcaption/unit_tests/test_sei.c Added
150
 
1
@@ -0,0 +1,148 @@
2
+/**********************************************************************************************/
3
+/* The MIT License                                                                            */
4
+/*                                                                                            */
5
+/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.       */
6
+/*                                                                                            */
7
+/* Permission is hereby granted, free of charge, to any person obtaining a copy               */
8
+/* of this software and associated documentation files (the "Software"), to deal              */
9
+/* in the Software without restriction, including without limitation the rights               */
10
+/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                  */
11
+/* copies of the Software, and to permit persons to whom the Software is                      */
12
+/* furnished to do so, subject to the following conditions:                                   */
13
+/*                                                                                            */
14
+/* The above copyright notice and this permission notice shall be included in                 */
15
+/* all copies or substantial portions of the Software.                                        */
16
+/*                                                                                            */
17
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR                 */
18
+/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                   */
19
+/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE                */
20
+/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                     */
21
+/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,              */
22
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN                  */
23
+/* THE SOFTWARE.                                                                              */
24
+/**********************************************************************************************/
25
+
26
+#include "avcsei.h"
27
+#include <stdio.h>
28
+#include <stdlib.h>
29
+
30
+uint8_t sei1[] = { 0x06, 0x04, 0x68, 0xB5, 0x00, 0x31, 0x47, 0x41, 0x39, 0x34, 0x03, 0xDF, 0xFF, 0xFC, 0xEC, 0xE5,
31
+                   0xFC, 0xAE, 0x80, 0xFC, 0x94, 0x52, 0xFC, 0x97, 0xA1, 0xFC, 0x2A, 0x20, 0xFC, 0xDC, 0x20, 0xFC,
32
+                   0x5E, 0x20, 0xFC, 0xDF, 0x20, 0xFC, 0xE0, 0x20, 0xFC, 0x91, 0x38, 0xFC, 0x20, 0x80, 0xFC, 0x91,
33
+                   0xBA, 0xFC, 0x20, 0xE9, 0xFC, 0x13, 0xA4, 0xFC, 0x20, 0xEF, 0xFC, 0x13, 0x26, 0xFC, 0x20, 0x75,
34
+                   0xFC, 0x92, 0xBC, 0xFC, 0x94, 0xF2, 0xFC, 0x97, 0xA1, 0xFC, 0x61, 0x80, 0xFC, 0x13, 0x31, 0xFC,
35
+                   0x20, 0xE5, 0xFC, 0x92, 0xB6, 0xFC, 0x20, 0xE9, 0xFC, 0x92, 0xB9, 0xFC, 0x20, 0xEF, 0xFC, 0x13,
36
+                   0xB3, 0xFC, 0x20, 0x75, 0xFC, 0x92, 0x25, 0xFC, 0x20, 0x80, 0xFF, 0x80,
37
+                 };
38
+
39
+uint8_t sei2[] = { 0x06, 0x04, 0x35, 0xB5, 0x00, 0x31, 0x47, 0x41, 0x39, 0x34, 0x03, 0xCE, 0xFF, 0xFC, 0x94, 0x26,
40
+                   0xFC, 0x94, 0xAD, 0xFC, 0x94, 0xF2, 0xFC, 0x43, 0xC1, 0xFC, 0xD0, 0x54, 0xFC, 0x49, 0x4F, 0xFC,
41
+                   0xCE, 0x20, 0xFC, 0x4C, 0x49, 0xFC, 0xCE, 0x45, 0xFC, 0xD3, 0x20, 0xFC, 0x52, 0x4F, 0xFC, 0x4C,
42
+                   0x4C, 0xFC, 0x20, 0xD5, 0xFC, 0xD0, 0x80, 0xFF, 0x80,
43
+                 };
44
+
45
+
46
+uint8_t sei3[] = { 0x06,
47
+                   0x04, 0x68, 0xB5, 0x00, 0x31, 0x47, 0x41, 0x39, 0x34, 0x03, 0xDF, 0xFF, 0xFC, 0xEC, 0xE5, 0xFC,
48
+                   0xAE, 0x80, 0xFC, 0x94, 0x52, 0xFC, 0x97, 0xA1, 0x00, 0x00, 0x03, 0x00, 0xFC, 0xDC, 0x20, 0xFC,
49
+                   0x5E, 0x20, 0xFC, 0xDF, 0x20, 0xFC, 0xE0, 0x20, 0xFC, 0x91, 0x38, 0xFC, 0x20, 0x80, 0xFC, 0x91,
50
+                   0xBA, 0xFC, 0x20, 0xE9, 0xFC, 0x13, 0xA4, 0xFC, 0x20, 0xEF, 0xFC, 0x13, 0x26, 0xFC, 0x20, 0x75,
51
+                   0xFC, 0x92, 0xBC, 0xFC, 0x94, 0xF2, 0xFC, 0x97, 0xA1, 0xFC, 0x61, 0x80, 0xFC, 0x13, 0x31, 0xFC,
52
+                   0x20, 0xE5, 0xFC, 0x92, 0xB6, 0xFC, 0x20, 0xE9, 0xFC, 0x92, 0xB9, 0xFC, 0x20, 0xEF, 0xFC, 0x13,
53
+                   0xB3, 0xFC, 0x20, 0x75, 0xFC, 0x92, 0x25, 0xFC, 0x20, 0x80, 0xFF,
54
+
55
+                   0x04, 0x68, 0xB5, 0x00, 0x31, 0x47, 0x41, 0x39, 0x34, 0x03, 0xDF, 0xFF, 0xFC, 0xEC, 0xE5,
56
+                   0xFC, 0xAE, 0x80, 0xFC, 0x94, 0x52, 0xFC, 0x97, 0xA1, 0x00, 0x00, 0x03, 0x00, 0xFC, 0xDC, 0x20,
57
+                   0xFC, 0x5E, 0x20, 0xFC, 0xDF, 0x20, 0xFC, 0xE0, 0x20, 0xFC, 0x91, 0x38, 0xFC, 0x20, 0x80, 0xFC,
58
+                   0x91, 0xBA, 0xFC, 0x20, 0xE9, 0xFC, 0x13, 0xA4, 0xFC, 0x20, 0xEF, 0xFC, 0x13, 0x26, 0xFC, 0x20,
59
+                   0x75, 0xFC, 0x92, 0xBC, 0xFC, 0x94, 0xF2, 0xFC, 0x97, 0xA1, 0xFC, 0x61, 0x80, 0xFC, 0x13, 0x31,
60
+                   0xFC, 0x20, 0xE5, 0xFC, 0x92, 0xB6, 0xFC, 0x20, 0xE9, 0xFC, 0x92, 0xB9, 0xFC, 0x20, 0xEF, 0xFC,
61
+                   0x13, 0xB3, 0xFC, 0x20, 0x75, 0xFC, 0x92, 0x25, 0xFC, 0x20, 0x80, 0xFF,
62
+                   0x80,
63
+                 };
64
+
65
+
66
+// TODO make SEI with multiple messages
67
+// TODO make SEI with emupation prevention
68
+
69
+
70
+uint8_t* read_file (const char* file, size_t* size)
71
+{
72
+    FILE* f = fopen (file, "rb");
73
+
74
+    if (! f) {
75
+        return 0;
76
+    }
77
+
78
+    fseek (f,0,SEEK_END);
79
+    (*size) = ftell (f);
80
+    fseek (f,0,SEEK_SET);
81
+    uint8_t* data = (uint8_t*) malloc (*size);
82
+
83
+    for (int i = 0 ; i < (*size) ;) {
84
+        i += fread (&data[i], 1, *size, f);
85
+    }
86
+
87
+    fclose (f);
88
+    return data;
89
+}
90
+
91
+int test_emulation_byte()
92
+{
93
+    avcsei_t sei;
94
+    avcsei_init (&sei);
95
+    avcsei_parse (&sei,sei3,sizeof (sei3));
96
+    avcsei_dump (&sei);
97
+    avcsei_free (&sei);
98
+}
99
+
100
+
101
+int main (int argc, const char** argv)
102
+{
103
+    // test_emulation_byte();
104
+    // return 0;
105
+
106
+    size_t size;
107
+    avcsei_t sei;
108
+    cea708_t cea708;
109
+    eia608_screen_t screen;
110
+    char screen_buf[EIA608_SCREEN_DUMP_BUF_SIZE];
111
+    char json_buf[EIA608_SCREEN_JSON_BUF_SIZE];
112
+
113
+    // uint8_t* data =
114
+    for (int i = 1 ; i < argc ; ++i) {
115
+        avcsei_init (&sei);
116
+        eia608_screen_init (&screen);
117
+        uint8_t* data = read_file (argv[i],&size);
118
+        avcsei_parse (&sei,data,size);
119
+        free (data);
120
+
121
+        // avcsei_parse (&sei,sei1,sizeof (sei1));
122
+
123
+        for (avcsei_message_t* msg = avcsei_message_head (&sei) ; msg ; msg = avcsei_message_next (msg)) {
124
+            if (sei_type_user_data_registered_itu_t_t35 == avcsei_message_type (msg)) {
125
+                // avcsei_dump (&sei);
126
+                avcsei_decode_cea708 (msg,&cea708);
127
+                int count = cea708_cc_count (&cea708.user_data);
128
+
129
+                for (int i = 0 ; i < count ; ++i) {
130
+                    cea708_cc_type_t type; int valid;
131
+                    uint16_t cc_data = cea708_cc_data (&cea708.user_data, i, &valid, &type);
132
+
133
+                    if (valid && (cc_type_ntsc_cc_field_1 == type || cc_type_ntsc_cc_field_2 == type)) {
134
+                        eia608_screen_decode (&screen,cc_data);
135
+                    }
136
+                }
137
+
138
+                // eia608_screen_dump (&screen, &screen_buf[0]);
139
+                // printf ("screen:\n%s\n",&screen_buf[0]);
140
+
141
+                eia608_screen_json (&screen, &json_buf[0]);
142
+                printf ("json:\n%s\n",&json_buf[0]);
143
+
144
+            }
145
+        }
146
+
147
+        avcsei_free (&sei);
148
+    }
149
+}
150
obs-studio-0.17.0.tar.xz/deps/libcaption/unit_tests/tos.scc Added
156
 
1
@@ -0,0 +1,154 @@
2
+Scenarist_SCC V1.0
3
+
4
+00:00:22:10    9420 94f2 97a2 d9ef 75a7 f2e5 2061 20ea e5f2 6b2c 2054 68ef 6dae 942c 8080 8080 942f
5
+
6
+00:00:23:28    9420 947c 97a2 4cef ef6b 2043 e5ec e961 2c20 f7e5 2068 6176 e520 f4ef 20e6 efec ecef f720 ef75 f220 7061 7373 e9ef 6e73 3b80 942c 8080 8080 942f
7
+
8
+00:00:25:16    9420 9440 aeae ae79 ef75 2068 6176 e520 79ef 75f2 20f2 ef62 eff4 e9e3 732c 2061 6e64 2049 94fe 9723 ea75 73f4 20f7 616e f420 f4ef 2062 e520 61f7 e573 ef6d e520 e96e 2073 7061 e3e5 ae80 942c 8080 8080 942f
9
+
10
+00:00:29:09    9420 9440 97a1 5768 7920 64ef 6ea7 f420 79ef 7520 ea75 73f4 2061 646d e9f4 20f4 6861 f480 94fe 97a2 79ef 75a7 f2e5 20e6 f2e5 616b e564 20ef 75f4 2062 7920 6d79 20f2 ef62 eff4 2068 616e 64bf 942c 8080 8080 942f
11
+
12
+00:00:33:19    9420 94e0 49a7 6d20 6eef f420 e6f2 e561 6be5 6420 ef75 f420 6279 ad20 e9f4 a773 aeae ae80 942c 8080 8080 942f
13
+
14
+00:00:36:10    9420 94f2 9723 aeae ae61 ecf2 e967 68f4 a120 46e9 6ee5 a180 942c 8080 8080 942f
15
+
16
+00:00:36:29    9420 945e 9723 49a7 6d20 e6f2 e561 6be5 6420 ef75 f4a1 2049 2068 6176 e520 6ee9 6768 f46d 61f2 e573 94f2 f468 61f4 2049 a76d 2062 e5e9 6e67 20e3 6861 73e5 64ae aeae 942c 8080 8080 942f
17
+
18
+00:00:39:27    9420 947c 97a2 aeae ae62 7920 f468 e573 e520 67e9 616e f420 f2ef 62ef f4e9 e320 e3ec 61f7 7320 efe6 2064 e561 f468 aeae ae80 942c 8080 8080 942f
19
+
20
+00:00:40:29    9420 9452 97a2 a246 ef75 f2f4 7920 79e5 61f2 7320 ec61 f4e5 f2a2 94e0 97a2 5768 61f4 e576 e5f2 2c20 5468 ef6d ae20 57e5 a7f2 e520 64ef 6ee5 ae80 942c 8080 8080 942f
21
+
22
+00:00:49:02    9420 94fe 9723 52ef 62ef f4a7 7320 6de5 6def f279 2073 796e e3e5 6420 616e 6420 ecef e36b e564 a180 942c 8080 8080 942f
23
+
24
+00:01:00:08    9420 94f2 97a1 5468 e973 20e9 7320 70f2 e5f4 f479 20e6 f2e5 616b 79ae 942c 8080 8080 942f
25
+
26
+00:01:56:03    9420 94e0 97a2 d368 ef75 ec64 6ea7 f420 79ef 7520 62e5 2064 eff7 6e20 f468 e5f2 e5bf 942c 8080 8080 942f
27
+
28
+00:02:09:29    9420 94fe 97a2 4920 68e5 61f2 6420 79ef 7520 6775 7973 20f4 61ec 6be9 6e67 20ec 6173 f420 6ee9 6768 f4ae 942c 8080 8080 942f
29
+
30
+00:02:15:02    9420 94e0 97a2 49f4 a773 206e eff4 206d 7920 e661 75ec f42c 2079 ef75 206b 6eef f7ae 942c 8080 8080 942f
31
+
32
+00:03:10:08    9420 94f4 97a1 c1f2 e520 79ef 7520 f2e5 6164 79bf 942c 8080 8080 942f
33
+
34
+00:03:11:24    9420 947c 9723 4fe6 20e3 ef75 f273 e520 79ef 75a7 f2e5 20f2 e561 6479 2c20 79ef 75a7 f2e5 2061 20f2 efe3 6b73 f461 f2ae 942c 8080 8080 942f
35
+
36
+00:03:16:02    9420 94e0 9723 c8ef f7a7 7320 e9f4 20ec efef 6be9 6e67 2c20 c261 f2ec e579 bf80 942c 8080 8080 942f
37
+
38
+00:03:17:27    9420 94fe 97a2 57e5 2073 68ef 75ec 6420 6861 76e5 2061 62ef 75f4 20f4 e56e 206d e96e 75f4 e573 aeae ae80 942c 8080 8080 942f
39
+
40
+00:03:20:19    9420 94f2 97a2 57e5 ecec 20f4 6861 f4a7 7320 70e5 f2e6 e5e3 f4ae 942c 8080 8080 942f
41
+
42
+00:03:22:05    9420 9440 57e5 a7f2 e520 ef6e 20e9 6e20 ef6e e5a1 20c1 ecec 2073 7973 f4e5 6d73 2067 efa1 94f4 97a1 d9e5 6168 2079 ef75 2c20 67ef a180 942c 8080 8080 942f
43
+
44
+00:03:26:29    9420 94e0 97a1 c7ef a120 cdef 76e5 2079 ef75 f220 6173 73e5 73a1 20c7 ef20 67ef 2067 efa1 942c 8080 8080 942f
45
+
46
+00:03:32:03    9420 94f2 4920 ecef 76e5 20e9 f4a1 2043 ef6d e520 ef6e 2c20 67ef a180 942c 8080 8080 942f
47
+
48
+00:03:42:08    9420 94f4 97a2 5468 61f4 a773 206e e9e3 e5ae 942c 8080 8080 942f
49
+
50
+00:03:43:18    9420 94f2 ceef f468 e96e 6720 f4ef 20f7 eff2 f279 2061 62ef 75f4 ae80 942c 8080 8080 942f
51
+
52
+00:03:45:11    9420 9476 97a1 5468 ef6d ae80 942c 8080 8080 942f
53
+
54
+00:03:50:07    9420 94f4 97a1 5468 e5f2 e520 7368 e520 e973 ae80 942c 8080 8080 942f
55
+
56
+00:03:52:27    9420 9476 97a2 ceef f7ae 942c 8080 8080 942f
57
+
58
+00:03:54:06    9420 94f4 97a1 d9ef 7520 ecef 76e5 2068 e5f2 ae80 942c 8080 8080 942f
59
+
60
+00:03:56:03    9420 94f2 97a2 d368 e520 e973 2079 ef75 f220 7061 7373 e9ef 6ea1 942c 8080 8080 942f
61
+
62
+00:03:59:04    9420 94f2 9723 c2e5 20f4 e56e 64e5 f220 f4ef 2068 e5f2 ae80 942c 8080 8080 942f
63
+
64
+00:04:00:15    9420 94e0 9723 c2e5 2068 ef6e e573 f4a1 2045 68ad 2062 e520 f4e5 6e64 e5f2 ae80 942c 8080 8080 942f
65
+
66
+00:04:04:02    9420 94f2 52e5 6de9 6e64 2068 e5f2 20f7 6861 f420 ecef 76e5 20e9 73ae 942c 8080 8080 942f
67
+
68
+00:04:51:05    9420 94f4 aeae ae61 6e64 2c20 61e3 f4e9 ef6e a180 942c 8080 8080 942f
69
+
70
+00:04:55:12    9420 94e0 97a1 cde5 6def f279 20ef 76e5 f2f7 f2e9 f4e5 20e9 6e20 70f2 ef67 f2e5 7373 a180 942c 8080 8080 942f
71
+
72
+00:04:58:02    9420 94f2 97a2 d9ef 75a7 f2e5 2061 20ea e5f2 6b2c 2054 68ef 6da1 942c 8080 8080 942f
73
+
74
+00:05:01:17    9420 94f2 9723 4f68 70ad 20d3 eff2 f279 a120 d3ef f2f2 79ae 942c 8080 8080 942f
75
+
76
+00:05:15:05    9420 94f4 97a2 4cef ef6b 2043 e5ec e961 ae80 942c 8080 8080 942f
77
+
78
+00:05:16:26    9420 94e0 57e5 2068 6176 e520 f4ef 20e6 efec ecef f720 ef75 f220 7061 7373 e9ef 6e73 ae80 942c 8080 8080 942f
79
+
80
+00:05:19:28    9420 94e0 9723 d9ef 7520 6861 76e5 2079 ef75 f220 f2ef 62ef f4e9 e373 aeae ae80 942c 8080 8080 942f
81
+
82
+00:05:23:20    9420 947c 9723 aeae ae61 6e64 2049 20ea 7573 f420 f761 6ef4 20f4 ef20 62e5 2061 f7e5 73ef 6de5 20e9 6e20 7370 61e3 e5ae 942c 8080 8080 942f
83
+
84
+00:05:37:21    9420 94fe 4f6b 6179 2c20 f468 e579 a7f2 e520 e3ef 6de9 6e67 ae20 54f7 ef20 6de9 6e75 f4e5 7320 ece5 e6f4 a180 942c 8080 8080 942f
85
+
86
+00:05:42:01    9420 94f2 9723 d370 e5e5 6420 e9f4 2075 702c 2054 68ef 6da1 942c 8080 8080 942f
87
+
88
+00:05:44:04    9420 94f4 97a2 d6e9 7661 e3e9 7373 e96d efa1 942c 8080 8080 942f
89
+
90
+00:05:45:05    9420 945e 97a2 5768 7920 64ef 6ea7 f420 79ef 7520 ea75 73f4 2061 646d e9f4 20f4 6861 f420 79ef 75a7 f2e5 94e0 97a1 e6f2 e561 6be5 6420 ef75 f420 6279 206d 7920 f2ef 62ef f420 6861 6e64 bf80 942c 8080 8080 942f
91
+
92
+00:05:54:26    9420 94e0 97a2 4ce9 73f4 e56e 2043 e5ec e961 2c20 4920 f761 7320 79ef 756e 67ae aeae 942c 8080 8080 942f
93
+
94
+00:05:58:18    9420 94f4 97a1 aeae ae61 6e64 2061 2064 e9e3 6bae 942c 8080 8080 942f
95
+
96
+00:05:59:18    9420 9452 c275 f420 f468 61f4 a773 206e ef20 f2e5 6173 ef6e 20f4 ef80 94f2 9723 64e5 73f4 f2ef 7920 f468 e520 f7ef f2ec 64ae 942c 8080 8080 942f
97
+
98
+00:06:04:00    9420 94f2 97a2 5768 7920 64ef e573 2068 e520 64ef 20f4 68e9 73bf 942c 8080 8080 942f
99
+
100
+00:06:05:12    9420 94e0 9723 57e5 2061 ecf2 e561 6479 20f4 f2e9 e564 20f4 6861 f420 ef6e e5a1 942c 8080 8080 942f
101
+
102
+00:06:10:21    9420 9476 97a1 c162 eff2 f4a1 942c 8080 8080 942f
103
+
104
+00:06:12:07    9420 9476 97a2 4375 f4a1 942c 8080 8080 942f
105
+
106
+00:06:13:06    9420 9476 5768 ef61 6161 a180 942c 8080 8080 942f
107
+
108
+00:06:18:06    9420 9476 5768 ef61 6161 a180 942c 8080 8080 942f
109
+
110
+00:06:20:06    9420 9476 ceef efef efef a180 942c 8080 8080 942f
111
+
112
+00:06:21:29    9420 94f2 97a2 d9ef 7520 62f2 ef6b e520 6d79 2068 e561 f2f4 ae80 942c 8080 8080 942f
113
+
114
+00:06:25:06    9420 9476 4920 6b6e eff7 ae80 942c 8080 8080 942f
115
+
116
+00:06:25:28    9420 94f2 d9ef 7520 e6ef f267 eff4 206d e520 ef6e 20e5 61f2 f468 ae80 942c 8080 8080 942f
117
+
118
+00:06:28:06    9420 9476 4920 6b6e eff7 ae80 942c 8080 8080 942f
119
+
120
+00:06:29:13    9420 94f2 4920 7368 ef75 ec64 20ea 7573 f420 e3f2 7573 6820 79ef 75ae 942c 8080 8080 942f
121
+
122
+00:06:35:07    9420 9476 97a2 49a7 6dad 942c 8080 8080 942f
123
+
124
+00:06:46:03    9420 94f4 9723 49a7 6d20 73ef f2f2 79ae 942c 8080 8080 942f
125
+
126
+00:06:49:02    9420 94f4 97a2 c7ef ef64 2061 64ad ece9 62ae 942c 8080 8080 942f
127
+
128
+00:06:58:01    9420 94f4 97a1 ceef f420 6d79 20e6 6175 ecf4 a180 942c 8080 8080 942f
129
+
130
+00:07:01:03    9420 94f4 9723 5468 e973 20f4 e96d e5ae 942c 8080 8080 942f
131
+
132
+00:07:07:01    9420 94f4 97a1 5175 e9e5 f420 ef6e 2073 e5f4 a180 942c 8080 8080 942f
133
+
134
+00:07:08:29    9420 94f2 9723 57e5 a7f2 e520 ef75 f420 efe6 20f4 e96d e5a1 942c 8080 8080 942f
135
+
136
+00:08:12:03    9420 9476 43ef 6de5 20ef 6ea1 942c 8080 8080 942f
137
+
138
+00:08:20:29    9420 94f4 97a2 52c1 c1c1 c1c1 c1c1 c1c8 a180 942c 8080 8080 942f
139
+
140
+00:08:22:24    9420 94f2 97a1 cde5 6def f279 20ef 76e5 f2f7 f2e9 f4e5 2c20 b9b0 25ae 942c 8080 8080 942f
141
+
142
+00:08:24:22    9420 94e0 9723 4361 70f4 61e9 6ea1 2057 e520 6861 76e5 20f4 ef20 6162 eff2 f4a1 942c 8080 8080 942f
143
+
144
+00:08:36:20    9420 94e0 97a1 5468 e520 f7ef f2ec 64a7 7320 e368 616e 67e5 642c 2043 e5ec e961 aeae ae80 942c 8080 8080 942f
145
+
146
+00:08:52:24    9420 94f2 97a2 aeae ae6d 6179 62e5 20f7 e520 e361 6e20 f4ef efae 942c 8080 8080 942f
147
+
148
+00:08:56:21    9420 94e0 9723 cde5 6def f279 20ef 76e5 f2f7 f2e9 f4e5 20e3 ef6d 70ec e5f4 e5a1 942c 8080 8080 942f
149
+
150
+00:09:17:29    9420 94f4 9723 d9ef 7520 6b6e eff7 ae80 942c 8080 8080 942f
151
+
152
+00:09:20:13    9420 947c 9723 5468 e5f2 e5a7 7320 6120 ece5 7373 ef6e 20f4 ef20 62e5 20ec e561 f26e e564 20e6 f2ef 6d20 f468 e973 ae80 942c 8080 8080 942f
153
+
154
+00:09:24:24    9420 94f2 97a2 43ef 75ec 64a7 6120 67ef 6ee5 20f7 eff2 73e5 ae80 942c 8080 8080 942f
155
+
156
obs-studio-0.16.6.tar.xz/deps/libff/libff/ff-demuxer.c -> obs-studio-0.17.0.tar.xz/deps/libff/libff/ff-demuxer.c Changed
10
 
1
@@ -377,7 +377,7 @@
2
    }
3
 
4
    if (avformat_open_input(format_context, demuxer->input,
5
-           input_format, NULL) != 0)
6
+           input_format, &demuxer->options.custom_options) != 0)
7
        return false;
8
 
9
    return avformat_find_stream_info(*format_context, NULL) >= 0;
10
obs-studio-0.16.6.tar.xz/deps/libff/libff/ff-demuxer.h -> obs-studio-0.17.0.tar.xz/deps/libff/libff/ff-demuxer.h Changed
9
 
1
@@ -40,6 +40,7 @@
2
    bool is_hw_decoding;
3
    bool is_looping;
4
    enum AVDiscard frame_drop;
5
+   AVDictionary *custom_options;
6
 };
7
 
8
 typedef struct ff_demuxer_options ff_demuxer_options_t;
9
obs-studio-0.16.6.tar.xz/libobs-d3d11/d3d11-rebuild.cpp -> obs-studio-0.17.0.tar.xz/libobs-d3d11/d3d11-rebuild.cpp Changed
48
 
1
@@ -31,15 +31,43 @@
2
        throw HRError("Failed to create buffer", hr);
3
 }
4
 
5
+void gs_texture_2d::RebuildSharedTextureFallback()
6
+{
7
+   td                  = {};
8
+   td.Width            = 2;
9
+   td.Height           = 2;
10
+   td.MipLevels        = 1;
11
+   td.Format           = DXGI_FORMAT_B8G8R8A8_UNORM;
12
+   td.ArraySize        = 1;
13
+   td.SampleDesc.Count = 1;
14
+
15
+   width      = td.Width;
16
+   height     = td.Height;
17
+   dxgiFormat = td.Format;
18
+   levels     = 1;
19
+
20
+   resourceDesc = {};
21
+   resourceDesc.Format              = td.Format;
22
+   resourceDesc.ViewDimension       = D3D11_SRV_DIMENSION_TEXTURE2D;
23
+   resourceDesc.Texture2D.MipLevels = 1;
24
+
25
+   isShared = false;
26
+}
27
+
28
 inline void gs_texture_2d::Rebuild(ID3D11Device *dev)
29
 {
30
    HRESULT hr;
31
    if (isShared) {
32
        hr = dev->OpenSharedResource((HANDLE)(uintptr_t)sharedHandle,
33
                __uuidof(ID3D11Texture2D), (void**)&texture);
34
-       if (FAILED(hr))
35
-           throw HRError("Failed to open shared 2D texture", hr);
36
-   } else {
37
+       if (FAILED(hr)) {
38
+           blog(LOG_WARNING, "Failed to rebuild shared texture: ",
39
+                   "0x%08lX", hr);
40
+           RebuildSharedTextureFallback();
41
+       }
42
+   }
43
+
44
+   if (!isShared) {
45
        hr = dev->CreateTexture2D(&td,
46
                data.size() ? srd.data() : nullptr,
47
                &texture);
48
obs-studio-0.16.6.tar.xz/libobs-d3d11/d3d11-shader.cpp -> obs-studio-0.17.0.tar.xz/libobs-d3d11/d3d11-shader.cpp Changed
24
 
1
@@ -201,6 +201,22 @@
2
        else
3
            throw HRError("Failed to compile shader", hr);
4
    }
5
+
6
+#ifdef DISASSEMBLE_SHADERS
7
+   ComPtr<ID3D10Blob> asmBlob;
8
+
9
+   if (!device->d3dDisassemble)
10
+       return;
11
+
12
+   hr = device->d3dDisassemble((*shader)->GetBufferPointer(),
13
+           (*shader)->GetBufferSize(), 0, nullptr, &asmBlob);
14
+
15
+   if (SUCCEEDED(hr) && !!asmBlob && asmBlob->GetBufferSize()) {
16
+       blog(LOG_INFO, "=============================================");
17
+       blog(LOG_INFO, "Disassembly output for shader '%s':\n%s",
18
+               file, asmBlob->GetBufferPointer());
19
+   }
20
+#endif
21
 }
22
 
23
 inline void gs_shader::UpdateParam(vector<uint8_t> &constData,
24
obs-studio-0.16.6.tar.xz/libobs-d3d11/d3d11-subsystem.cpp -> obs-studio-0.17.0.tar.xz/libobs-d3d11/d3d11-subsystem.cpp Changed
13
 
1
@@ -181,6 +181,11 @@
2
        if (module) {
3
            d3dCompile = (pD3DCompile)GetProcAddress(module,
4
                    "D3DCompile");
5
+
6
+#ifdef DISASSEMBLE_SHADERS
7
+           d3dDisassemble = (pD3DDisassemble)GetProcAddress(
8
+                   module, "D3DDisassemble");
9
+#endif
10
            if (d3dCompile) {
11
                return;
12
            }
13
obs-studio-0.16.6.tar.xz/libobs-d3d11/d3d11-subsystem.hpp -> obs-studio-0.17.0.tar.xz/libobs-d3d11/d3d11-subsystem.hpp Changed
28
 
1
@@ -37,6 +37,8 @@
2
 #include <util/windows/ComPtr.hpp>
3
 #include <util/windows/HRError.hpp>
4
 
5
+// #define DISASSEMBLE_SHADERS
6
+
7
 struct shader_var;
8
 struct shader_sampler;
9
 struct gs_vertex_shader;
10
@@ -360,6 +362,7 @@
11
    void InitRenderTargets();
12
    void BackupTexture(const uint8_t **data);
13
 
14
+   void RebuildSharedTextureFallback();
15
    inline void Rebuild(ID3D11Device *dev);
16
 
17
    inline void Release()
18
@@ -801,6 +804,9 @@
19
    D3D11_PRIMITIVE_TOPOLOGY    curToplogy;
20
 
21
    pD3DCompile                 d3dCompile = nullptr;
22
+#ifdef DISASSEMBLE_SHADERS
23
+   pD3DDisassemble             d3dDisassemble = nullptr;
24
+#endif
25
 
26
    gs_rect                     viewport;
27
 
28
obs-studio-0.16.6.tar.xz/libobs-opengl/gl-x11.c -> obs-studio-0.17.0.tar.xz/libobs-opengl/gl-x11.c Changed
15
 
1
@@ -587,7 +587,12 @@
2
        initialized = true;
3
    }
4
 
5
-   /* TODO: Handle XCB events. */
6
+   xcb_connection_t *xcb_conn = XGetXCBConnection(display);
7
+   xcb_generic_event_t *xcb_event;
8
+   while((xcb_event = xcb_poll_for_event(xcb_conn))) {
9
+       /* TODO: Handle XCB events. */
10
+       free(xcb_event);
11
+   }
12
 
13
    switch (swap_type) {
14
    case SWAP_TYPE_EXT:    glXSwapIntervalEXT(display, window, 0); break;
15
obs-studio-0.16.6.tar.xz/libobs/CMakeLists.txt -> obs-studio-0.17.0.tar.xz/libobs/CMakeLists.txt Changed
14
 
1
@@ -347,6 +347,12 @@
2
 source_group("util\\Source Files" FILES ${libobs_util_SOURCES})
3
 source_group("util\\Header Files" FILES ${libobs_util_HEADERS})
4
 
5
+if(BUILD_CAPTIONS)
6
+   include_directories(${CMAKE_SOURCE_DIR}/deps/libcaption)
7
+   set(libobs_PLATFORM_DEPS
8
+       ${libobs_PLATFORM_DEPS}
9
+       caption)
10
+endif()
11
 
12
 add_library(libobs SHARED ${libobs_SOURCES} ${libobs_HEADERS})
13
 
14
obs-studio-0.16.6.tar.xz/libobs/graphics/vec2.h -> obs-studio-0.17.0.tar.xz/libobs/graphics/vec2.h Changed
10
 
1
@@ -106,7 +106,7 @@
2
 
3
 static inline float vec2_dot(const struct vec2 *v1, const struct vec2 *v2)
4
 {
5
-   return (v1->x+v2->x) * (v1->y+v2->y);
6
+   return v1->x*v2->x + v1->y*v2->y;
7
 }
8
 
9
 static inline float vec2_len(const struct vec2 *v)
10
obs-studio-0.16.6.tar.xz/libobs/media-io/audio-io.h -> obs-studio-0.17.0.tar.xz/libobs/media-io/audio-io.h Changed
10
 
1
@@ -25,7 +25,7 @@
2
 extern "C" {
3
 #endif
4
 
5
-#define MAX_AUDIO_MIXES     4
6
+#define MAX_AUDIO_MIXES     6
7
 #define MAX_AUDIO_CHANNELS  2
8
 #define AUDIO_OUTPUT_FRAMES 1024
9
 
10
obs-studio-0.16.6.tar.xz/libobs/obs-avc.c -> obs-studio-0.17.0.tar.xz/libobs/obs-avc.c Changed
21
 
1
@@ -132,15 +132,17 @@
2
 {
3
    struct array_output_data output;
4
    struct serializer s;
5
+   long ref = 1;
6
 
7
    array_output_serializer_init(&s, &output);
8
    *avc_packet = *src;
9
 
10
+   serialize(&s, &ref, sizeof(ref));
11
    serialize_avc_data(&s, src->data, src->size, &avc_packet->keyframe,
12
            &avc_packet->priority);
13
 
14
-   avc_packet->data          = output.bytes.array;
15
-   avc_packet->size          = output.bytes.num;
16
+   avc_packet->data          = output.bytes.array + sizeof(ref);
17
+   avc_packet->size          = output.bytes.num - sizeof(ref);
18
    avc_packet->drop_priority = get_drop_priority(avc_packet->priority);
19
 }
20
 
21
obs-studio-0.16.6.tar.xz/libobs/obs-config.h -> obs-studio-0.17.0.tar.xz/libobs/obs-config.h Changed
26
 
1
@@ -27,21 +27,21 @@
2
 /*
3
  * Increment if major breaking API changes
4
  */
5
-#define LIBOBS_API_MAJOR_VER  0 /* 0 means development, anything can break */
6
+#define LIBOBS_API_MAJOR_VER  17
7
 
8
 /*
9
  * Increment if backward-compatible additions
10
  *
11
  * Reset to zero each major version
12
  */
13
-#define LIBOBS_API_MINOR_VER  16
14
+#define LIBOBS_API_MINOR_VER  0
15
 
16
 /*
17
  * Increment if backward-compatible bug fix
18
  *
19
  * Reset to zero each major or minor version
20
  */
21
-#define LIBOBS_API_PATCH_VER  6
22
+#define LIBOBS_API_PATCH_VER  0
23
 
24
 #define MAKE_SEMANTIC_VERSION(major, minor, patch) \
25
                              ((major << 24) | \
26
obs-studio-0.16.6.tar.xz/libobs/obs-display.c -> obs-studio-0.17.0.tar.xz/libobs/obs-display.c Changed
115
 
1
@@ -23,6 +23,7 @@
2
        const struct gs_init_data *graphics_data)
3
 {
4
    pthread_mutex_init_value(&display->draw_callbacks_mutex);
5
+   pthread_mutex_init_value(&display->draw_info_mutex);
6
 
7
    if (graphics_data) {
8
        display->swap = gs_swapchain_create(graphics_data);
9
@@ -40,6 +41,10 @@
10
        blog(LOG_ERROR, "obs_display_init: Failed to create mutex");
11
        return false;
12
    }
13
+   if (pthread_mutex_init(&display->draw_info_mutex, NULL) != 0) {
14
+       blog(LOG_ERROR, "obs_display_init: Failed to create mutex");
15
+       return false;
16
+   }
17
 
18
    display->background_color = 0x4C4C4C;
19
    display->enabled = true;
20
@@ -73,6 +78,7 @@
21
 void obs_display_free(obs_display_t *display)
22
 {
23
    pthread_mutex_destroy(&display->draw_callbacks_mutex);
24
+   pthread_mutex_destroy(&display->draw_info_mutex);
25
    da_free(display->draw_callbacks);
26
 
27
    if (display->swap) {
28
@@ -103,13 +109,13 @@
29
 {
30
    if (!display) return;
31
 
32
-   pthread_mutex_lock(&display->draw_callbacks_mutex);
33
+   pthread_mutex_lock(&display->draw_info_mutex);
34
 
35
    display->cx = cx;
36
    display->cy = cy;
37
    display->size_changed = true;
38
 
39
-   pthread_mutex_unlock(&display->draw_callbacks_mutex);
40
+   pthread_mutex_unlock(&display->draw_info_mutex);
41
 }
42
 
43
 void obs_display_add_draw_callback(obs_display_t *display,
44
@@ -138,16 +144,15 @@
45
    pthread_mutex_unlock(&display->draw_callbacks_mutex);
46
 }
47
 
48
-static inline void render_display_begin(struct obs_display *display)
49
+static inline void render_display_begin(struct obs_display *display,
50
+       uint32_t cx, uint32_t cy, bool size_changed)
51
 {
52
    struct vec4 clear_color;
53
 
54
    gs_load_swapchain(display ? display->swap : NULL);
55
 
56
-   if (display->size_changed) {
57
-       gs_resize(display->cx, display->cy);
58
-       display->size_changed = false;
59
-   }
60
+   if (size_changed)
61
+       gs_resize(cx, cy);
62
 
63
    gs_begin_scene();
64
 
65
@@ -161,9 +166,8 @@
66
    /* gs_enable_blending(false); */
67
    gs_set_cull_mode(GS_NEITHER);
68
 
69
-   gs_ortho(0.0f, (float)display->cx,
70
-           0.0f, (float)display->cy, -100.0f, 100.0f);
71
-   gs_set_viewport(0, 0, display->cx, display->cy);
72
+   gs_ortho(0.0f, (float)cx, 0.0f, (float)cy, -100.0f, 100.0f);
73
+   gs_set_viewport(0, 0, cx, cy);
74
 }
75
 
76
 static inline void render_display_end()
77
@@ -174,9 +178,27 @@
78
 
79
 void render_display(struct obs_display *display)
80
 {
81
+   uint32_t cx, cy;
82
+   bool size_changed;
83
+
84
    if (!display || !display->enabled) return;
85
 
86
-   render_display_begin(display);
87
+   /* -------------------------------------------- */
88
+
89
+   pthread_mutex_lock(&display->draw_info_mutex);
90
+
91
+   cx = display->cx;
92
+   cy = display->cy;
93
+   size_changed = display->size_changed;
94
+
95
+   if (size_changed)
96
+       display->size_changed = false;
97
+
98
+   pthread_mutex_unlock(&display->draw_info_mutex);
99
+
100
+   /* -------------------------------------------- */
101
+
102
+   render_display_begin(display, cx, cy, size_changed);
103
 
104
    pthread_mutex_lock(&display->draw_callbacks_mutex);
105
 
106
@@ -184,7 +206,7 @@
107
        struct draw_callback *callback;
108
        callback = display->draw_callbacks.array+i;
109
 
110
-       callback->draw(callback->param, display->cx, display->cy);
111
+       callback->draw(callback->param, cx, cy);
112
    }
113
 
114
    pthread_mutex_unlock(&display->draw_callbacks_mutex);
115
obs-studio-0.16.6.tar.xz/libobs/obs-encoder.c -> obs-studio-0.17.0.tar.xz/libobs/obs-encoder.c Changed
61
 
1
@@ -1035,17 +1035,55 @@
2
    pthread_mutex_unlock(&encoder->outputs_mutex);
3
 }
4
 
5
-void obs_duplicate_encoder_packet(struct encoder_packet *dst,
6
+void obs_encoder_packet_create_instance(struct encoder_packet *dst,
7
        const struct encoder_packet *src)
8
 {
9
+   long *p_refs;
10
+
11
    *dst = *src;
12
-   dst->data = bmemdup(src->data, src->size);
13
+   p_refs = bmalloc(src->size + sizeof(long));
14
+   dst->data = (void*)(p_refs + 1);
15
+   *p_refs = 1;
16
+   memcpy(dst->data, src->data, src->size);
17
+}
18
+
19
+void obs_duplicate_encoder_packet(struct encoder_packet *dst,
20
+       const struct encoder_packet *src)
21
+{
22
+   obs_encoder_packet_create_instance(dst, src);
23
 }
24
 
25
 void obs_free_encoder_packet(struct encoder_packet *packet)
26
 {
27
-   bfree(packet->data);
28
-   memset(packet, 0, sizeof(struct encoder_packet));
29
+   obs_encoder_packet_release(packet);
30
+}
31
+
32
+void obs_encoder_packet_ref(struct encoder_packet *dst,
33
+       struct encoder_packet *src)
34
+{
35
+   if (!src)
36
+       return;
37
+
38
+   if (src->data) {
39
+       long *p_refs = ((long*)src->data) - 1;
40
+       os_atomic_inc_long(p_refs);
41
+   }
42
+
43
+   *dst = *src;
44
+}
45
+
46
+void obs_encoder_packet_release(struct encoder_packet *pkt)
47
+{
48
+   if (!pkt)
49
+       return;
50
+
51
+   if (pkt->data) {
52
+       long *p_refs = ((long*)pkt->data) - 1;
53
+       if (os_atomic_dec_long(p_refs) == 0)
54
+           bfree(p_refs);
55
+   }
56
+
57
+   memset(pkt, 0, sizeof(struct encoder_packet));
58
 }
59
 
60
 void obs_encoder_set_preferred_video_format(obs_encoder_t *encoder,
61
obs-studio-0.16.6.tar.xz/libobs/obs-internal.h -> obs-studio-0.17.0.tar.xz/libobs/obs-internal.h Changed
53
 
1
@@ -199,6 +199,7 @@
2
    uint32_t                        background_color;
3
    gs_swapchain_t                  *swap;
4
    pthread_mutex_t                 draw_callbacks_mutex;
5
+   pthread_mutex_t                 draw_info_mutex;
6
    DARRAY(struct draw_callback)    draw_callbacks;
7
 
8
    struct obs_display              *next;
9
@@ -718,8 +719,6 @@
10
        return GS_RGBA;
11
    else if (format == VIDEO_FORMAT_BGRA)
12
        return GS_BGRA;
13
-   else if (format == VIDEO_FORMAT_Y800)
14
-       return GS_R8;
15
 
16
    return GS_BGRX;
17
 }
18
@@ -774,6 +773,13 @@
19
    struct obs_output *output;
20
 };
21
 
22
+#define CAPTION_LINE_CHARS (32)
23
+#define CAPTION_LINE_BYTES (4*CAPTION_LINE_CHARS)
24
+struct caption_text {
25
+   char text[CAPTION_LINE_BYTES+1];
26
+   struct caption_text *next;
27
+};
28
+
29
 struct obs_output {
30
    struct obs_context_data         context;
31
    struct obs_output_info          info;
32
@@ -828,6 +834,11 @@
33
    struct video_scale_info         video_conversion;
34
    struct audio_convert_info       audio_conversion;
35
 
36
+   pthread_mutex_t                 caption_mutex;
37
+   double                          caption_timestamp;
38
+   struct caption_text             *caption_head;
39
+   struct caption_text             *caption_tail;
40
+
41
    bool                            valid;
42
 
43
    uint64_t                        active_delay_ns;
44
@@ -864,6 +875,8 @@
45
 extern void obs_output_remove_encoder(struct obs_output *output,
46
        struct obs_encoder *encoder);
47
 
48
+extern void obs_encoder_packet_create_instance(struct encoder_packet *dst,
49
+       const struct encoder_packet *src);
50
 void obs_output_destroy(obs_output_t *output);
51
 
52
 
53
obs-studio-0.16.6.tar.xz/libobs/obs-output-delay.c -> obs-studio-0.17.0.tar.xz/libobs/obs-output-delay.c Changed
28
 
1
@@ -35,7 +35,7 @@
2
 
3
    dd.msg = DELAY_MSG_PACKET;
4
    dd.ts  = t;
5
-   obs_duplicate_encoder_packet(&dd.packet, packet);
6
+   obs_encoder_packet_create_instance(&dd.packet, packet);
7
 
8
    pthread_mutex_lock(&output->delay_mutex);
9
    circlebuf_push_back(&output->delay_data, &dd, sizeof(dd));
10
@@ -48,7 +48,7 @@
11
    switch (dd->msg) {
12
    case DELAY_MSG_PACKET:
13
        if (!delay_active(output) || !delay_capturing(output))
14
-           obs_free_encoder_packet(&dd->packet);
15
+           obs_encoder_packet_release(&dd->packet);
16
        else
17
            output->delay_callback(output, &dd->packet);
18
        break;
19
@@ -68,7 +68,7 @@
20
    while (output->delay_data.size) {
21
        circlebuf_pop_front(&output->delay_data, &dd, sizeof(dd));
22
        if (dd.msg == DELAY_MSG_PACKET) {
23
-           obs_free_encoder_packet(&dd.packet);
24
+           obs_encoder_packet_release(&dd.packet);
25
        }
26
    }
27
 
28
obs-studio-0.16.6.tar.xz/libobs/obs-output.c -> obs-studio-0.17.0.tar.xz/libobs/obs-output.c Changed
288
 
1
@@ -20,6 +20,11 @@
2
 #include "obs.h"
3
 #include "obs-internal.h"
4
 
5
+#if BUILD_CAPTIONS
6
+#include <caption/caption.h>
7
+#include <caption/avc.h>
8
+#endif
9
+
10
 static inline bool active(const struct obs_output *output)
11
 {
12
    return os_atomic_load_bool(&output->active);
13
@@ -99,11 +104,14 @@
14
    output = bzalloc(sizeof(struct obs_output));
15
    pthread_mutex_init_value(&output->interleaved_mutex);
16
    pthread_mutex_init_value(&output->delay_mutex);
17
+   pthread_mutex_init_value(&output->caption_mutex);
18
 
19
    if (pthread_mutex_init(&output->interleaved_mutex, NULL) != 0)
20
        goto fail;
21
    if (pthread_mutex_init(&output->delay_mutex, NULL) != 0)
22
        goto fail;
23
+   if (pthread_mutex_init(&output->caption_mutex, NULL) != 0)
24
+       goto fail;
25
    if (os_event_init(&output->stopping_event, OS_EVENT_TYPE_MANUAL) != 0)
26
        goto fail;
27
    if (!init_output_handlers(output, name, settings, hotkey_data))
28
@@ -129,12 +137,6 @@
29
    if (ret < 0)
30
        goto fail;
31
 
32
-   if (info)
33
-       output->context.data = info->create(output->context.settings,
34
-               output);
35
-   if (!output->context.data)
36
-       blog(LOG_ERROR, "Failed to create output '%s'!", name);
37
-
38
    output->reconnect_retry_sec = 2;
39
    output->reconnect_retry_max = 20;
40
    output->valid               = true;
41
@@ -146,6 +148,12 @@
42
            &obs->data.outputs_mutex,
43
            &obs->data.first_output);
44
 
45
+   if (info)
46
+       output->context.data = info->create(output->context.settings,
47
+               output);
48
+   if (!output->context.data)
49
+       blog(LOG_ERROR, "Failed to create output '%s'!", name);
50
+
51
    blog(LOG_DEBUG, "output '%s' (%s) created", name, id);
52
    return output;
53
 
54
@@ -157,7 +165,7 @@
55
 static inline void free_packets(struct obs_output *output)
56
 {
57
    for (size_t i = 0; i < output->interleaved_packets.num; i++)
58
-       obs_free_encoder_packet(output->interleaved_packets.array+i);
59
+       obs_encoder_packet_release(output->interleaved_packets.array+i);
60
    da_free(output->interleaved_packets);
61
 }
62
 
63
@@ -196,6 +204,7 @@
64
        }
65
 
66
        os_event_destroy(output->stopping_event);
67
+       pthread_mutex_destroy(&output->caption_mutex);
68
        pthread_mutex_destroy(&output->interleaved_mutex);
69
        pthread_mutex_destroy(&output->delay_mutex);
70
        os_event_destroy(output->reconnect_stop_event);
71
@@ -235,6 +244,7 @@
72
    if (os_atomic_load_long(&output->delay_restart_refs))
73
        os_atomic_dec_long(&output->delay_restart_refs);
74
 
75
+   output->caption_timestamp = 0;
76
    return success;
77
 }
78
 
79
@@ -356,6 +366,12 @@
80
        signal_stop(output);
81
        os_event_signal(output->stopping_event);
82
    }
83
+
84
+   while (output->caption_head) {
85
+       output->caption_tail = output->caption_head->next;
86
+       bfree(output->caption_head);
87
+       output->caption_head = output->caption_tail;
88
+   }
89
 }
90
 
91
 void obs_output_stop(obs_output_t *output)
92
@@ -942,6 +958,56 @@
93
        return output->highest_video_ts > packet->dts_usec;
94
 }
95
 
96
+#if BUILD_CAPTIONS
97
+static const uint8_t nal_start[4] = {0, 0, 0, 1};
98
+
99
+static bool add_caption(struct obs_output *output, struct encoder_packet *out)
100
+{
101
+   struct encoder_packet backup = *out;
102
+   caption_frame_t cf;
103
+   sei_t sei;
104
+   uint8_t *data;
105
+   size_t size;
106
+   long ref = 1;
107
+
108
+   DARRAY(uint8_t) out_data;
109
+
110
+   if (out->priority > 1)
111
+       return false;
112
+
113
+   sei_init(&sei);
114
+
115
+   da_init(out_data);
116
+   da_push_back_array(out_data, &ref, sizeof(ref));
117
+   da_push_back_array(out_data, out->data, out->size);
118
+
119
+   caption_frame_init(&cf);
120
+   caption_frame_from_text(&cf, &output->caption_head->text[0]);
121
+
122
+   sei_from_caption_frame(&sei, &cf);
123
+
124
+   data = malloc(sei_render_size(&sei));
125
+   size = sei_render(&sei, data);
126
+   /* TODO SEI should come after AUD/SPS/PPS, but before any VCL */
127
+   da_push_back_array(out_data, nal_start, 4);
128
+   da_push_back_array(out_data, data, size);
129
+   free(data);
130
+
131
+   obs_encoder_packet_release(out);
132
+
133
+   *out = backup;
134
+   out->data = (uint8_t*)out_data.array + sizeof(ref);
135
+   out->size = out_data.num - sizeof(ref);
136
+
137
+   sei_free(&sei);
138
+
139
+   struct caption_text *next = output->caption_head->next;
140
+   bfree(output->caption_head);
141
+   output->caption_head = next;
142
+   return true;
143
+}
144
+#endif
145
+
146
 static inline void send_interleaved(struct obs_output *output)
147
 {
148
    struct encoder_packet out = output->interleaved_packets.array[0];
149
@@ -952,12 +1018,37 @@
150
    if (!has_higher_opposing_ts(output, &out))
151
        return;
152
 
153
-   if (out.type == OBS_ENCODER_VIDEO)
154
+   da_erase(output->interleaved_packets, 0);
155
+
156
+   if (out.type == OBS_ENCODER_VIDEO) {
157
        output->total_frames++;
158
 
159
-   da_erase(output->interleaved_packets, 0);
160
+#if BUILD_CAPTIONS
161
+       pthread_mutex_lock(&output->caption_mutex);
162
+
163
+       double frame_timestamp = (out.pts * out.timebase_num) /
164
+           (double)out.timebase_den;
165
+
166
+       /* TODO if output->caption_timestamp is more than 5 seconds
167
+        * old, send empty frame */
168
+       if (output->caption_head &&
169
+           output->caption_timestamp <= frame_timestamp) {
170
+           blog(LOG_INFO,"Sending caption: %f \"%s\"",
171
+                   frame_timestamp,
172
+                   &output->caption_head->text[0]);
173
+
174
+           if (add_caption(output, &out)) {
175
+               output->caption_timestamp =
176
+                   frame_timestamp + 2.0;
177
+           }
178
+       }
179
+
180
+       pthread_mutex_unlock(&output->caption_mutex);
181
+#endif
182
+   }
183
+
184
    output->info.encoded_packet(output->context.data, &out);
185
-   obs_free_encoder_packet(&out);
186
+   obs_encoder_packet_release(&out);
187
 }
188
 
189
 static inline void set_higher_ts(struct obs_output *output,
190
@@ -1056,7 +1147,7 @@
191
    for (size_t i = 0; i < idx; i++) {
192
        struct encoder_packet *packet =
193
            &output->interleaved_packets.array[i];
194
-       obs_free_encoder_packet(packet);
195
+       obs_encoder_packet_release(packet);
196
    }
197
 
198
    da_erase_range(output->interleaved_packets, 0, idx);
199
@@ -1304,7 +1395,7 @@
200
        pthread_mutex_unlock(&output->interleaved_mutex);
201
 
202
        if (output->active_delay_ns)
203
-           obs_free_encoder_packet(packet);
204
+           obs_encoder_packet_release(packet);
205
        return;
206
    }
207
 
208
@@ -1313,7 +1404,7 @@
209
    if (output->active_delay_ns)
210
        out = *packet;
211
    else
212
-       obs_duplicate_encoder_packet(&out, packet);
213
+       obs_encoder_packet_create_instance(&out, packet);
214
 
215
    if (was_started)
216
        apply_interleaved_packet_offset(output, &out);
217
@@ -1356,7 +1447,7 @@
218
    }
219
 
220
    if (output->active_delay_ns)
221
-       obs_free_encoder_packet(packet);
222
+       obs_encoder_packet_release(packet);
223
 }
224
 
225
 static void default_raw_video_callback(void *param, struct video_data *frame)
226
@@ -1954,3 +2045,61 @@
227
    return obs_output_valid(output, "obs_output_get_id")
228
        ? output->info.id : NULL;
229
 }
230
+
231
+#if BUILD_CAPTIONS
232
+static struct caption_text *caption_text_new(const char *text, size_t bytes,
233
+       struct caption_text *tail, struct caption_text **head)
234
+{
235
+   struct caption_text *next = bzalloc(sizeof(struct caption_text));
236
+   snprintf(&next->text[0], CAPTION_LINE_BYTES + 1, "%.*s", bytes, text);
237
+
238
+   if (!*head) {
239
+       *head = next;
240
+   } else {
241
+       tail->next = next;
242
+   }
243
+
244
+   return next;
245
+}
246
+
247
+void obs_output_output_caption_text1(obs_output_t *output, const char *text)
248
+{
249
+   if (!obs_output_valid(output, "obs_output_output_caption_text1"))
250
+       return;
251
+   if (!active(output))
252
+       return;
253
+
254
+   // split text into  32 charcter strings
255
+   int size = (int)strlen(text);
256
+   int r;
257
+   size_t char_count;
258
+   size_t line_length = 0;
259
+   size_t trimmed_length = 0;
260
+
261
+   blog(LOG_DEBUG, "Caption text: %s", text);
262
+
263
+   pthread_mutex_lock(&output->caption_mutex);
264
+
265
+   for (r = 0 ; 0 < size && CAPTION_LINE_CHARS > r; ++r) {
266
+       line_length = utf8_line_length(text);
267
+       trimmed_length = utf8_trimmed_length(text, line_length);
268
+       char_count = utf8_char_count(text, trimmed_length);
269
+
270
+       if (SCREEN_COLS < char_count) {
271
+           char_count = utf8_wrap_length(text, CAPTION_LINE_CHARS);
272
+           line_length = utf8_string_length(text, char_count + 1);
273
+       }
274
+
275
+       output->caption_tail = caption_text_new(
276
+               text,
277
+               line_length,
278
+               output->caption_tail,
279
+               &output->caption_head);
280
+
281
+       text += line_length;
282
+       size -= (int)line_length;
283
+   }
284
+
285
+   pthread_mutex_unlock(&output->caption_mutex);
286
+}
287
+#endif
288
obs-studio-0.16.6.tar.xz/libobs/obs-scene.c -> obs-studio-0.17.0.tar.xz/libobs/obs-scene.c Changed
96
 
1
@@ -741,11 +741,13 @@
2
    bool cur_visible = item->visible;
3
    uint64_t frame_num = 0;
4
    size_t deref_count = 0;
5
-   float *buf;
6
+   float *buf = NULL;
7
 
8
-   if (!*p_buf)
9
-       *p_buf = malloc(AUDIO_OUTPUT_FRAMES * sizeof(float));
10
-   buf = *p_buf;
11
+   if (p_buf) {
12
+       if (!*p_buf)
13
+           *p_buf = malloc(AUDIO_OUTPUT_FRAMES * sizeof(float));
14
+       buf = *p_buf;
15
+   }
16
 
17
    pthread_mutex_lock(&item->actions_mutex);
18
 
19
@@ -760,7 +762,7 @@
20
        new_frame_num = (timestamp - ts) * (uint64_t)sample_rate /
21
            1000000000ULL;
22
 
23
-       if (new_frame_num >= AUDIO_OUTPUT_FRAMES)
24
+       if (ts && new_frame_num >= AUDIO_OUTPUT_FRAMES)
25
            break;
26
 
27
        da_erase(item->audio_actions, i--);
28
@@ -769,7 +771,7 @@
29
        if (!item->visible)
30
            deref_count++;
31
 
32
-       if (new_frame_num > frame_num) {
33
+       if (buf && new_frame_num > frame_num) {
34
            for (; frame_num < new_frame_num; frame_num++)
35
                buf[frame_num] = cur_visible ? 1.0f : 0.0f;
36
        }
37
@@ -777,8 +779,10 @@
38
        cur_visible = item->visible;
39
    }
40
 
41
-   for (; frame_num < AUDIO_OUTPUT_FRAMES; frame_num++)
42
-       buf[frame_num] = cur_visible ? 1.0f : 0.0f;
43
+   if (buf) {
44
+       for (; frame_num < AUDIO_OUTPUT_FRAMES; frame_num++)
45
+           buf[frame_num] = cur_visible ? 1.0f : 0.0f;
46
+   }
47
 
48
    pthread_mutex_unlock(&item->actions_mutex);
49
 
50
@@ -790,7 +794,7 @@
51
    }
52
 }
53
 
54
-static inline bool apply_scene_item_volume(struct obs_scene_item *item,
55
+static bool apply_scene_item_volume(struct obs_scene_item *item,
56
        float **buf, uint64_t ts, size_t sample_rate)
57
 {
58
    bool actions_pending;
59
@@ -808,7 +812,7 @@
60
        uint64_t duration = (uint64_t)AUDIO_OUTPUT_FRAMES *
61
            1000000000ULL / (uint64_t)sample_rate;
62
 
63
-       if (action.timestamp < (ts + duration)) {
64
+       if (!ts || action.timestamp < (ts + duration)) {
65
            apply_scene_item_audio_actions(item, buf, ts,
66
                    sample_rate);
67
            return true;
68
@@ -818,6 +822,12 @@
69
    return false;
70
 }
71
 
72
+static void process_all_audio_actions(struct obs_scene_item *item,
73
+       size_t sample_rate)
74
+{
75
+   while (apply_scene_item_volume(item, NULL, 0, sample_rate));
76
+}
77
+
78
 static void mix_audio_with_buf(float *p_out, float *p_in, float *buf_in,
79
        size_t pos, size_t count)
80
 {
81
@@ -867,6 +877,14 @@
82
    }
83
 
84
    if (!timestamp) {
85
+       /* just process all pending audio actions if no audio playing,
86
+        * otherwise audio actions will just never be processed */
87
+       item = scene->first_item;
88
+       while (item) {
89
+           process_all_audio_actions(item, sample_rate);
90
+           item = item->next;
91
+       }
92
+
93
        audio_unlock(scene);
94
        return false;
95
    }
96
obs-studio-0.16.6.tar.xz/libobs/obs-source.c -> obs-studio-0.17.0.tar.xz/libobs/obs-source.c Changed
93
 
1
@@ -174,7 +174,7 @@
2
    source->control = bzalloc(sizeof(obs_weak_source_t));
3
    source->deinterlace_top_first = true;
4
    source->control->source = source;
5
-   source->audio_mixers = 0xF;
6
+   source->audio_mixers = 0xFF;
7
 
8
    if (is_audio_source(source)) {
9
        pthread_mutex_lock(&obs->data.audio_sources_mutex);
10
@@ -2098,6 +2098,41 @@
11
                dst->linesize[plane] * lines);
12
 }
13
 
14
+static void copy_frame_data_line_y800(uint32_t *dst, uint8_t *src, uint8_t *end)
15
+{
16
+   while (src < end) {
17
+       register uint32_t val = *(src++);
18
+       val |= (val << 8);
19
+       val |= (val << 16);
20
+       *(dst++) = val;
21
+   }
22
+}
23
+
24
+static inline void copy_frame_data_y800(struct obs_source_frame *dst,
25
+       const struct obs_source_frame *src)
26
+{
27
+   uint32_t *ptr_dst;
28
+   uint8_t  *ptr_src;
29
+   uint8_t  *src_end;
30
+
31
+   if ((src->linesize[0] * 4) != dst->linesize[0]) {
32
+       for (uint32_t cy = 0; cy < src->height; cy++) {
33
+           ptr_dst = (uint32_t*)
34
+               (dst->data[0] + cy * dst->linesize[0]);
35
+           ptr_src = (src->data[0] + cy * src->linesize[0]);
36
+           src_end = ptr_src + src->width;
37
+
38
+           copy_frame_data_line_y800(ptr_dst, ptr_src, src_end);
39
+       }
40
+   } else {
41
+       ptr_dst = (uint32_t*)dst->data[0];
42
+       ptr_src = (uint8_t *)src->data[0];
43
+       src_end = ptr_src + src->height * src->linesize[0];
44
+
45
+       copy_frame_data_line_y800(ptr_dst, ptr_src, src_end);
46
+   }
47
+}
48
+
49
 static void copy_frame_data(struct obs_source_frame *dst,
50
        const struct obs_source_frame *src)
51
 {
52
@@ -2111,7 +2146,7 @@
53
        memcpy(dst->color_range_max, src->color_range_max, size);
54
    }
55
 
56
-   switch (dst->format) {
57
+   switch (src->format) {
58
    case VIDEO_FORMAT_I420:
59
        copy_frame_data_plane(dst, src, 0, dst->height);
60
        copy_frame_data_plane(dst, src, 1, dst->height/2);
61
@@ -2132,12 +2167,16 @@
62
    case VIDEO_FORMAT_YVYU:
63
    case VIDEO_FORMAT_YUY2:
64
    case VIDEO_FORMAT_UYVY:
65
-   case VIDEO_FORMAT_Y800:
66
    case VIDEO_FORMAT_NONE:
67
    case VIDEO_FORMAT_RGBA:
68
    case VIDEO_FORMAT_BGRA:
69
    case VIDEO_FORMAT_BGRX:
70
        copy_frame_data_plane(dst, src, 0, dst->height);
71
+       break;
72
+
73
+   case VIDEO_FORMAT_Y800:
74
+       copy_frame_data_y800(dst, src);
75
+       break;
76
    }
77
 }
78
 
79
@@ -2218,8 +2257,12 @@
80
 
81
    if (!new_frame) {
82
        struct async_frame new_af;
83
+       enum video_format format = frame->format;
84
+
85
+       if (format == VIDEO_FORMAT_Y800)
86
+           format = VIDEO_FORMAT_BGRX;
87
 
88
-       new_frame = obs_source_frame_create(frame->format,
89
+       new_frame = obs_source_frame_create(format,
90
                frame->width, frame->height);
91
        new_af.frame = new_frame;
92
        new_af.used = true;
93
obs-studio-0.16.6.tar.xz/libobs/obs.h -> obs-studio-0.17.0.tar.xz/libobs/obs.h Changed
42
 
1
@@ -533,8 +533,8 @@
2
 EXPORT gs_effect_t *obs_get_base_effect(enum obs_base_effect effect);
3
 
4
 /* DEPRECATED: gets texture_rect default effect */
5
-DEPRECATED_START EXPORT gs_effect_t *obs_get_default_rect_effect(void)
6
-   DEPRECATED_END;
7
+DEPRECATED
8
+EXPORT gs_effect_t *obs_get_default_rect_effect(void);
9
 
10
 /** Returns the primary obs signal handler */
11
 EXPORT signal_handler_t *obs_get_signal_handler(void);
12
@@ -1460,6 +1460,11 @@
13
 
14
 EXPORT const char *obs_output_get_id(const obs_output_t *output);
15
 
16
+#if BUILD_CAPTIONS
17
+EXPORT void obs_output_output_caption_text1(obs_output_t *output,
18
+       const char *text);
19
+#endif
20
+
21
 /* ------------------------------------------------------------------------- */
22
 /* Functions used by outputs */
23
 
24
@@ -1651,11 +1656,17 @@
25
 EXPORT uint32_t obs_get_encoder_caps(const char *encoder_id);
26
 
27
 /** Duplicates an encoder packet */
28
+DEPRECATED
29
 EXPORT void obs_duplicate_encoder_packet(struct encoder_packet *dst,
30
        const struct encoder_packet *src);
31
 
32
+DEPRECATED
33
 EXPORT void obs_free_encoder_packet(struct encoder_packet *packet);
34
 
35
+EXPORT void obs_encoder_packet_ref(struct encoder_packet *dst,
36
+       struct encoder_packet *src);
37
+EXPORT void obs_encoder_packet_release(struct encoder_packet *packet);
38
+
39
 
40
 /* ------------------------------------------------------------------------- */
41
 /* Stream Services */
42
obs-studio-0.16.6.tar.xz/libobs/obsconfig.h.in -> obs-studio-0.17.0.tar.xz/libobs/obsconfig.h.in Changed
21
 
1
@@ -1,10 +1,19 @@
2
 
3
 #pragma once
4
 
5
+#ifndef ON
6
+#define ON 1
7
+#endif
8
+
9
+#ifndef OFF
10
+#define OFF 0
11
+#endif
12
+
13
 #define OBS_VERSION "@OBS_VERSION@"
14
 #define OBS_DATA_PATH "@OBS_DATA_PATH@"
15
 #define OBS_INSTALL_PREFIX "@OBS_INSTALL_PREFIX@"
16
 #define OBS_PLUGIN_DESTINATION "@OBS_PLUGIN_DESTINATION@"
17
 #define OBS_RELATIVE_PREFIX "@OBS_RELATIVE_PREFIX@"
18
 #define OBS_UNIX_STRUCTURE @OBS_UNIX_STRUCTURE@
19
+#define BUILD_CAPTIONS @BUILD_CAPTIONS@
20
 #define HAVE_DBUS @HAVE_DBUS@
21
obs-studio-0.16.6.tar.xz/libobs/util/c99defs.h -> obs-studio-0.17.0.tar.xz/libobs/util/c99defs.h Changed
23
 
1
@@ -24,19 +24,15 @@
2
 #define UNUSED_PARAMETER(param) (void)param
3
 
4
 #ifdef _MSC_VER
5
-#define DEPRECATED_START __declspec(deprecated)
6
-#define DEPRECATED_END
7
+#define DEPRECATED __declspec(deprecated)
8
 #define FORCE_INLINE __forceinline
9
 #else
10
-#define DEPRECATED_START
11
-#define DEPRECATED_END __attribute__ ((deprecated))
12
+#define DEPRECATED __attribute__ ((deprecated))
13
 #define FORCE_INLINE inline __attribute__((always_inline))
14
 #endif
15
 
16
 #ifdef _MSC_VER
17
 
18
-#pragma warning (disable : 4996)
19
-
20
 /* Microsoft is one of the most inept companies on the face of the planet.
21
  * The fact that even visual studio 2013 doesn't support the standard 'inline'
22
  * keyword is so incredibly stupid that I just can't imagine what sort of
23
obs-studio-0.16.6.tar.xz/libobs/util/circlebuf.h -> obs-studio-0.17.0.tar.xz/libobs/util/circlebuf.h Changed
22
 
1
@@ -254,6 +254,20 @@
2
        cb->end_pos -= size;
3
 }
4
 
5
+static inline void *circlebuf_data(struct circlebuf *cb, size_t idx)
6
+{
7
+   uint8_t *ptr = (uint8_t*)cb->data;
8
+   size_t offset = cb->start_pos + idx;
9
+
10
+   if (idx > cb->size)
11
+       return NULL;
12
+
13
+   if (offset >= cb->capacity)
14
+       offset -= cb->capacity;
15
+
16
+   return ptr + offset;
17
+}
18
+
19
 #ifdef __cplusplus
20
 }
21
 #endif
22
obs-studio-0.16.6.tar.xz/libobs/util/platform.c -> obs-studio-0.17.0.tar.xz/libobs/util/platform.c Changed
133
 
1
@@ -16,6 +16,7 @@
2
 
3
 #define _FILE_OFFSET_BITS 64
4
 
5
+#include <time.h>
6
 #include <errno.h>
7
 #include <stdlib.h>
8
 #include <locale.h>
9
@@ -657,3 +658,123 @@
10
 
11
    return path + pos;
12
 }
13
+
14
+static inline bool valid_string(const char *str)
15
+{
16
+   while (str && *str) {
17
+       if (*(str++) != ' ')
18
+           return true;
19
+   }
20
+
21
+   return false;
22
+}
23
+
24
+static void replace_text(struct dstr *str, size_t pos, size_t len,
25
+       const char *new_text)
26
+{
27
+   struct dstr front = {0};
28
+   struct dstr back = {0};
29
+
30
+   dstr_left(&front, str, pos);
31
+   dstr_right(&back, str, pos + len);
32
+   dstr_copy_dstr(str, &front);
33
+   dstr_cat(str, new_text);
34
+   dstr_cat_dstr(str, &back);
35
+   dstr_free(&front);
36
+   dstr_free(&back);
37
+}
38
+
39
+static void erase_ch(struct dstr *str, size_t pos)
40
+{
41
+   struct dstr new_str = {0};
42
+   dstr_left(&new_str, str, pos);
43
+   dstr_cat(&new_str, str->array + pos + 1);
44
+   dstr_free(str);
45
+   *str = new_str;
46
+}
47
+
48
+char *os_generate_formatted_filename(const char *extension, bool space,
49
+       const char *format)
50
+{
51
+   time_t now = time(0);
52
+   struct tm *cur_time;
53
+   cur_time = localtime(&now);
54
+
55
+   const size_t spec_count = 23;
56
+   static const char *spec[][2] = {
57
+       {"%CCYY", "%Y"},
58
+       {"%YY",   "%y"},
59
+       {"%MM",   "%m"},
60
+       {"%DD",   "%d"},
61
+       {"%hh",   "%H"},
62
+       {"%mm",   "%M"},
63
+       {"%ss",   "%S"},
64
+       {"%%",    "%%"},
65
+
66
+       {"%a",    ""},
67
+       {"%A",    ""},
68
+       {"%b",    ""},
69
+       {"%B",    ""},
70
+       {"%d",    ""},
71
+       {"%H",    ""},
72
+       {"%I",    ""},
73
+       {"%m",    ""},
74
+       {"%M",    ""},
75
+       {"%p",    ""},
76
+       {"%S",    ""},
77
+       {"%y",    ""},
78
+       {"%Y",    ""},
79
+       {"%z",    ""},
80
+       {"%Z",    ""},
81
+   };
82
+
83
+   char convert[128] = {0};
84
+   struct dstr sf;
85
+   struct dstr c = {0};
86
+   size_t pos = 0;
87
+
88
+   dstr_init_copy(&sf, format);
89
+
90
+   while (pos < sf.len) {
91
+       for (size_t i = 0; i < spec_count && !convert[0]; i++) {
92
+           size_t len = strlen(spec[i][0]);
93
+
94
+           const char *cmp = sf.array + pos;
95
+
96
+           if (astrcmp_n(cmp, spec[i][0], len) == 0) {
97
+               if (strlen(spec[i][1]))
98
+                   strftime(convert, sizeof(convert),
99
+                           spec[i][1], cur_time);
100
+               else
101
+                   strftime(convert, sizeof(convert),
102
+                           spec[i][0], cur_time);
103
+
104
+
105
+               dstr_copy(&c, convert);
106
+               if (c.len && valid_string(c.array))
107
+                   replace_text(&sf, pos, len, convert);
108
+           }
109
+       }
110
+
111
+       if (convert[0]) {
112
+           pos += strlen(convert);
113
+           convert[0] = 0;
114
+       } else if (!convert[0] && sf.array[pos] == '%') {
115
+           erase_ch(&sf, pos);
116
+       } else {
117
+           pos++;
118
+       }
119
+   }
120
+
121
+   if (!space)
122
+       dstr_replace(&sf, " ", "_");
123
+
124
+   dstr_cat_ch(&sf, '.');
125
+   dstr_cat(&sf, extension);
126
+   dstr_free(&c);
127
+
128
+   if (sf.len > 255)
129
+       dstr_mid(&sf, &sf, 0, 255);
130
+
131
+   return sf.array;
132
+}
133
obs-studio-0.16.6.tar.xz/libobs/util/platform.h -> obs-studio-0.17.0.tar.xz/libobs/util/platform.h Changed
11
 
1
@@ -162,6 +162,9 @@
2
 EXPORT int os_rename(const char *old_path, const char *new_path);
3
 EXPORT int os_copyfile(const char *file_in, const char *file_out);
4
 
5
+EXPORT char *os_generate_formatted_filename(const char *extension, bool space,
6
+       const char *format);
7
+
8
 struct os_inhibit_info;
9
 typedef struct os_inhibit_info os_inhibit_t;
10
 
11
obs-studio-0.16.6.tar.xz/plugins/decklink/data/locale/tr-TR.ini -> obs-studio-0.17.0.tar.xz/plugins/decklink/data/locale/tr-TR.ini Changed
7
 
1
@@ -2,4 +2,5 @@
2
 Device="Aygıt"
3
 Mode="Mod"
4
 Buffering="Arabelleği Kullan"
5
+PixelFormat="Piksel Biçimi"
6
 
7
obs-studio-0.16.6.tar.xz/plugins/enc-amf/#Resources/PATCH_NOTES.md -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/#Resources/PATCH_NOTES.md Changed
40
 
1
@@ -1,29 +1,11 @@
2
-# Multi-GPU Support And Filler Data Fix (Hotfix 2)
3
-With this update the encoder plugin now supports multi-GPU setups, such as RX 480 + R9 390, R9 285 + R9 290, and others. You can select which GPU to use with the Advanced View Mode. The UI will also now update according to the supported features of the selected GPU and by default uses the primary GPU. Unsupported features will be hidden, just like unused features.
4
+# 1.4.3.4 - Crimson ReLive Compatibility Update (Hotfix 1)
5
+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.
6
 
7
-The 'Filler Data' property has now been fixed, Delta QP for B-Pictures is now visible when not using Constant QP, 'Memory Type' and 'Surface Format' have been removed and 'CABAC' has been replaced with 'Coding Type'. 'Memory Type' is now automatically using the best available and 'Surface Format' is taken from OBS settings.
8
-
9
-Additionally a crash with AMD Hybrid/Switchable GPU setups was fixed and these systems should now be able to use the encoder. It will now default to using the best available AMD GPU in the system if it can detect it.
10
-
11
-Hotfix 2: Fixed a potential crash when opening settings.
12
-Hotfix 1: Fixed Presets not being applied properly
13
-
14
-## Notes
15
-
16
-Due to the nature of changes since 1.3 users might experience that their settings have vanished or are incorrect. Please revalidate your settings or even create a clean profile to work off of.
17
+Hotfix 1: The Driver update also broke VBAQ, but it caused less issues than the Full Range flag. This has been fixed.
18
 
19
 ## Changelog
20
-
21
-* (Hotfix 2) Fixed: Potential crash when opening the settings.
22
-* (Hotfix 1) Fixed: Presets were not being applied properly.
23
-* Added: Full multi-GPU encoding support.
24
-* Added: 'Coding Type' property which replaces 'CABAC'.
25
-* Fixed: Filler Data was always being forced on for CBR.
26
-* Fixed: Users should now be able to modify Delta QP for B-Pictures even when not using Constant QP.
27
-* Fixed: Crash on OBS start on AMD Hybrid/Switchable GPU systems.
28
-* Changed: Default device is always the primary/best available AMD GPU in the system.
29
-* Changed: B-Picture properties will be properly hidden now if not in use.
30
-* Changed: B-Pictures defaults to 0 and B-Picture Reference defaults to Disabled.
31
-* Removed: 'Memory Type' property as the plugin will now always use the best available API.
32
-* Removed: 'Surface Format' property as the plugin will now use the OBS settings for this.
33
-* Removed: Deprecated encoder entry has been fully removed now.
34
\ No newline at end of file
35
+* Hotfix 1: Experimental Property VBAQ would not be properly set.
36
+* Hotfix 1: Runtime and Compiled Against version numbers were switched around.
37
+* Fixed: Experimental Full Range Color mode no longer causes encoding to fail. (Fixes #175)
38
+* Changed: Queue status log messages have been reduced to once per second instead of once per frame.
39
+* Changed: First submission log message now show the time in seconds instead of nanoseconds.
40
obs-studio-0.16.6.tar.xz/plugins/enc-amf/#Resources/package.in.bat -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/#Resources/package.in.bat Changed
6
 
1
@@ -16,4 +16,3 @@
2
 "%InnoSetup%" /cc "Installer.iss"
3
 
4
 POPD
5
-PAUSE
6
obs-studio-0.16.6.tar.xz/plugins/enc-amf/CMakeLists.txt -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/CMakeLists.txt Changed
50
 
1
@@ -3,26 +3,30 @@
2
 # Shared (OBS Studio & Standalone)
3
 PROJECT(enc-amf)
4
 SET(enc-amf_HEADERS
5
-   "Include/amd-amf.h"
6
-   "Include/amd-amf-vce.h"
7
-   "Include/amd-amf-vce-capabilities.h"
8
+   "Include/amf.h"
9
+   "Include/amf-capabilities.h"
10
+   "Include/amf-h264.h"
11
    "Include/api-base.h"
12
    "Include/api-d3d9.h"
13
    "Include/api-d3d11.h"
14
+   "Include/api-host.h"
15
+   "Include/api-opengl.h"
16
    "Include/enc-h264.h"
17
    "Include/plugin.h"
18
    "${PROJECT_BINARY_DIR}/Include/Version.h"
19
 )
20
 SET(enc-amf_SOURCES
21
-   "Source/amd-amf.cpp"
22
-   "Source/amd-amf-vce.cpp"
23
-   "Source/amd-amf-vce-capabilities.cpp"
24
+   "Source/amf.cpp"
25
+   "Source/amf-capabilities.cpp"
26
+   "Source/amf-h264.cpp"
27
    "Source/api-base.cpp"
28
+   "Source/api-host.cpp"
29
    "Source/api-d3d9.cpp"
30
    "Source/api-d3d11.cpp"
31
+   "Source/api-opengl.cpp"
32
    "Source/enc-h264.cpp"
33
-   "Source/plugin.cpp"
34
    "Source/misc-util.cpp"
35
+   "Source/plugin.cpp"
36
 )
37
 SET(enc-amf_LIBRARIES
38
    version
39
@@ -32,8 +36,8 @@
40
 # Version
41
 SET(enc-amf_VERSION_MAJOR 1)
42
 SET(enc-amf_VERSION_MINOR 4)
43
-SET(enc-amf_VERSION_PATCH 2)
44
-SET(enc-amf_VERSION_BUILD 3)
45
+SET(enc-amf_VERSION_PATCH 3)
46
+SET(enc-amf_VERSION_BUILD 4)
47
 configure_file(
48
    "${PROJECT_SOURCE_DIR}/#Resources/package.in.bat"
49
    "${PROJECT_SOURCE_DIR}/#Resources/package.bat"
50
obs-studio-0.16.6.tar.xz/plugins/enc-amf/CONTRIBUTING.md -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/CONTRIBUTING.md Changed
159
 
1
@@ -1,83 +1,89 @@
2
-# Reporting Issues
3
-
4
-Before you report an issue, please read the [Troubleshooting Guide](https://github.com/Xaymar/obs-studio_amf-encoder-plugin/wiki/Troubleshooting-Guide).
5
-It contains a step-by-step guide on how to solve your issue and even includes a FAQ for you to read through.
6
-
7
-# Git and the Project
8
-
9
-## Committing Changes
10
-
11
-Read [this wiki page for information](https://github.com/Xaymar/obs-studio_amf-encoder-plugin/wiki/Contributing) and please follow it. Rebasing a bunch of pushed commits is terrible for anyone involved.
12
-
13
-## Pull Requests
14
+# Contributing
15
+It's great to hear that you want to contribute to the project! So let's get you started.
16
+
17
+## Reporting Issues, Requesting Features, etc.
18
+Before you report an issue, please read the [Troubleshooting Guide](https://github.com/Xaymar/obs-studio_amf-encoder-plugin/wiki/Troubleshooting-Guide). It contains a step-by-step guide on how to solve your issue and even includes a FAQ for you to read through. If you request a certain feature, make sure that it is actually possible to implement this feature.
19
+
20
+## Changing the Project
21
+The first step to starting off is to get the project building so that you can actually test your changes yourself.
22
+
23
+### Prerequisites
24
+* [CMake Build Tool](https://cmake.org/)
25
+* [Visual Studio® 2013](http://visualstudio.com/), [Visual Studio® 2015](http://visualstudio.com/) or newer
26
+* [Open Broadcaster Software Studio](https://github.com/jp9000/obs-studio)
27
+* [AMDs Advanced Media Framework SDK](https://github.com/GPUOpen-LibrariesAndSDKs/AMF)
28
+* Windows 10 SDK (Version 10586 or better) *[Windows Only]*
29
+* Optional: [InnoSetup](http://www.jrsoftware.org/isinfo.php) for building a Standalone Installer
30
+
31
+### Step 1: Build Open Broadcaster Studio
32
+This is necessary so the plugin itself has something to link against. Simply build OBS Studio with the same configuration (or do a Batch Build for all configurations) and you are good to go.
33
+
34
+### Step 2: Configure the Project
35
+1. Point CMake at the Source Code and tell it to put binaries in /build32 (32-Bit) or /build64 (64-bit).
36
+2. Configure the Project
37
+3. Set PATH_AMDAMFSDK to where you cloned the AMD Advanced Media Framework SDK to.
38
+4. Set PATH_OBSStudio to where you cloned Open Broadcaster Software Studio to.
39
+5. Generate the Project files
40
+6. You should now have a Solution file in the /build32 or /build64 folder.
41
+
42
+### Step 3: Building the Project
43
+To verify that everything worked right you should now attempt to build the project with the generated solution file. If something did not work right, make sure that you have all prerequisites and start again from step 1.
44
+Once the building is complete you will notice a new folder called /#Build. This folder will always contain the latest files from a build, no matter the configuration. 
45
+
46
+### Step 4: Test the built Project
47
+Copy the files from /#Build to a OBS Studio installation (Portable or Static) and try to use your changes.
48
+
49
+## Git and the Project
50
+Version Control plays a large role in managing things and keeping in touch with changes.
51
+
52
+### Modules
53
+The plugin itself is made up of several sub-modules:
54
+
55
+* AMF: amf.cpp, amf.h, amf-capabilities.cpp, amf-capabilities.h
56
+* H264: amf-h264.cpp, amf-h264.h, enc-h264.cpp, enc-h264.h
57
+* H265: amf-h265.cpp, amf-h265.h, enc-h265.cpp, enc-h265.h
58
+* API: api-base.cpp, api-base.h
59
+* API-OGL: api-opengl.cpp, api-opengl.h
60
+* API-D3D9: api-d3d9.cpp, api-d3d9.h
61
+* API-D3D11: api-d3d11.cpp, api-d3d11.h
62
+* API-Host: api-host.cpp, api-host.h
63
+* Utilities: misc-util.cpp
64
+* Locale: Any locale files
65
+* Resources: Any resource files
66
+
67
+### Commits
68
+Commits should ideally only contain one group of changes. For example if you change how the H264 Color Format is called, that change would be prefixed by H264 and contain all the files this changes.
69
+
70
+#### Messages
71
+The first line of a message should not be longer than 80 characters and be prefixed by the module it changes. If it changes more than one separate them by comma. If it changes all of them use the prefix 'project'.
72
+
73
+### Pull Requests
74
 
75
 Pull Request titles should follow the guidelines for committing changes and also have a short description of what the change does.
76
 
77
-# Building
78
-
79
-## Step 1: Get the pre-requisites
80
-This plugin is included in the Open Broadcaster Studio project itself. This is only necessary if you wish to verify functionality with a standalone build.
81
-
82
-### Pre-Requisites
83
-* [Visual Studio® 2013 or Visual Studio® 2015 (Community or better)](http://visualstudio.com/)
84
-* Windows 10 SDK (Version 10586 or better, bundled with Visual Studio)
85
-* [OBS Studio](https://github.com/jp9000/obs-studio)
86
-* [AMF SDK](https://github.com/GPUOpen-LibrariesAndSDKs/AMF)
87
-* [InnoSetup](http://www.jrsoftware.org/isinfo.php)
88
-* CMake
89
-
90
-## Step 2: Configure with CMake
91
-Point CMake at the source code and use either /build32 for 32-bit or /build64 for 64-bit as the binaries path.
92
-
93
-The following variables are needed to be set for a successful build:
94
-
95
-* PATH_AMDAMFSDK - Path to the cloned AMF SDK repository.
96
-* PATH_OBSStudio - Path to the cloned OBS Studio repository.
97
-
98
-Once you have set these, you can generate the project files.
99
-
100
-## Step 3: Build with CMake
101
-1. Open the project file 
102
-2. Build
103
-
104
-Binaries will be located in /#Build and in the chosen binary path. An Installer can be created using the package.bat in /#Resources.
105
-
106
-## Step 3: Verify Functionality
107
-
108
-*[You can only do this with an AMD APU or GPU installed](https://github.com/Xaymar/obs-studio_amf-encoder-plugin/wiki/Hardware,-GCN-and-VCE-Limits)*.  
109
-Install the plugin into your OBS Studio installation or test environment and select it in either Simple Output Mode or Advanced Output Mode. It should encode fine without crashing at any point.
110
-
111
-# Coding Standard
112
-
113
+## Coding Standard
114
 The entire Project is written in C++ and as such follows common C++ writing practices.
115
 
116
-## Namespaces
117
-
118
+### Namespaces
119
 Namespaces should be named in *Pascal Case*. You may create a nested namespace that is 3 levels deep, not more.
120
 
121
-## Enumerations
122
+### Structures and Classes
123
+Structures and Classes should be named using *Pascal Case* and should be inside a namespace. A structure or class not in a namespace must have relevance to the entire code.
124
+
125
+#### Methods
126
+Methods should be named in *Pascal Case* and always reside in the class it belongs to.
127
+
128
+#### Members
129
+Members should be prefixed by 'm_' and then use a *Pascal Case* name. There is no special prefix per-type, per-usage or per-source.
130
 
131
+### Enumerations
132
 Enumerations should be named in *Pascal Case* and be inside a namespace or class.  
133
 Enumeration Constants should always be prefixed by the enumeration name so no ambiguity exists.
134
 
135
-## Functions
136
-
137
+### Functions
138
 Functions should be named in *Pascal Case* and should always be inside a namespace or class.
139
 Ideally your function should be either inlinable or have parameters passed by reference for optimization.
140
 
141
-## Classes
142
-
143
-Classes should be named in *Pascal Case* and should always be inside a namespace - a class not in a namespace must be really important to everything.
144
-
145
-### Methods (Class-specific Functions)
146
-
147
-Methods should be named in *Pascal Case* and always reside in the class it belongs to.
148
-
149
-### Members (Class-specific Variables)
150
-
151
-Members should be prefixed by 'm_' and then use a *Pascal Case* name. There is no special prefix per-type, per-usage or per-source.
152
-
153
-## Variables
154
-
155
-Variables should be named in *camel Case*
156
+### Variables
157
+Variables should be named in *camel Case*.
158
 
159
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/amf-capabilities.h Added
114
 
1
@@ -0,0 +1,111 @@
2
+/*
3
+MIT License
4
+
5
+Copyright (c) 2016 Michael Fabian Dirks
6
+
7
+Permission is hereby granted, free of charge, to any person obtaining a copy
8
+of this software and associated documentation files (the "Software"), to deal
9
+in the Software without restriction, including without limitation the rights
10
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+copies of the Software, and to permit persons to whom the Software is
12
+furnished to do so, subject to the following conditions:
13
+
14
+The above copyright notice and this permission notice shall be included in all
15
+copies or substantial portions of the Software.
16
+
17
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+SOFTWARE.
24
+*/
25
+
26
+#pragma once
27
+//////////////////////////////////////////////////////////////////////////
28
+// Includes
29
+//////////////////////////////////////////////////////////////////////////
30
+#include <stdint.h>
31
+#include <inttypes.h>
32
+#include <vector>
33
+#include <list>
34
+#include <map>
35
+#include <tuple>
36
+
37
+// Plugin
38
+#include "plugin.h"
39
+#include "amf.h"
40
+#include "amf-h264.h"
41
+#include "api-base.h"
42
+
43
+// AMF
44
+#include "components\ComponentCaps.h"
45
+
46
+//////////////////////////////////////////////////////////////////////////
47
+// Code
48
+//////////////////////////////////////////////////////////////////////////
49
+
50
+namespace Plugin {
51
+   namespace AMD {
52
+       volatile struct VCEDeviceCapabilities {
53
+           amf::AMF_ACCELERATION_TYPE acceleration_type;
54
+           uint32_t maxProfile;
55
+           uint32_t maxProfileLevel;
56
+           uint32_t maxBitrate;
57
+           uint32_t minReferenceFrames;
58
+           uint32_t maxReferenceFrames;
59
+           bool supportsBFrames;
60
+           bool supportsFixedSliceMode;
61
+           uint32_t maxTemporalLayers;
62
+           uint32_t maxNumOfStreams;
63
+           uint32_t maxNumOfHwInstances;
64
+
65
+           struct IOCaps {
66
+               int32_t minWidth, maxWidth;
67
+               int32_t minHeight, maxHeight;
68
+               bool supportsInterlaced;
69
+               uint32_t verticalAlignment;
70
+
71
+               std::vector<std::pair<amf::AMF_SURFACE_FORMAT, bool>> formats;
72
+               std::vector<std::pair<amf::AMF_MEMORY_TYPE, bool>> memoryTypes;
73
+           } input, output;
74
+
75
+           Plugin::AMD::VCEDeviceCapabilities::VCEDeviceCapabilities();
76
+       };
77
+
78
+       class VCECapabilities {
79
+           //////////////////////////////////////////////////////////////////////////
80
+           // Singleton
81
+           //////////////////////////////////////////////////////////////////////////
82
+           public:
83
+           static std::shared_ptr<Plugin::AMD::VCECapabilities> GetInstance();
84
+           static void ReportCapabilities(std::shared_ptr<Plugin::API::Base> api);
85
+           static void ReportAdapterCapabilities(std::shared_ptr<Plugin::API::Base> api,
86
+               Plugin::API::Adapter adapter);
87
+           static void ReportAdapterTypeCapabilities(std::shared_ptr<Plugin::API::Base> api,
88
+               Plugin::API::Adapter adapter,
89
+               VCEEncoderType type);
90
+           static void ReportAdapterTypeIOCapabilities(std::shared_ptr<Plugin::API::Base> api,
91
+               Plugin::API::Adapter adapter,
92
+               VCEEncoderType type,
93
+               bool output);
94
+
95
+           //////////////////////////////////////////////////////////////////////////
96
+           // Class
97
+           //////////////////////////////////////////////////////////////////////////
98
+           public:
99
+           VCECapabilities();
100
+           ~VCECapabilities();
101
+
102
+           bool Refresh();
103
+           std::vector<std::pair<VCEEncoderType, VCEDeviceCapabilities>>
104
+               GetAllAdapterCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter);
105
+           VCEDeviceCapabilities
106
+               GetAdapterCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter, VCEEncoderType type);
107
+
108
+           private:
109
+           std::map<std::tuple<std::string, Plugin::API::Adapter, Plugin::AMD::VCEEncoderType>, VCEDeviceCapabilities> capabilityMap;
110
+       };
111
+   }
112
+}
113
\ No newline at end of file
114
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/amf-h264.h Added
509
 
1
@@ -0,0 +1,506 @@
2
+/*
3
+MIT License
4
+
5
+Copyright (c) 2016 Michael Fabian Dirks
6
+
7
+Permission is hereby granted, free of charge, to any person obtaining a copy
8
+of this software and associated documentation files (the "Software"), to deal
9
+in the Software without restriction, including without limitation the rights
10
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+copies of the Software, and to permit persons to whom the Software is
12
+furnished to do so, subject to the following conditions:
13
+
14
+The above copyright notice and this permission notice shall be included in all
15
+copies or substantial portions of the Software.
16
+
17
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+SOFTWARE.
24
+*/
25
+
26
+#pragma once
27
+//////////////////////////////////////////////////////////////////////////
28
+// Includes
29
+//////////////////////////////////////////////////////////////////////////
30
+#include <condition_variable>
31
+#include <algorithm>
32
+#include <mutex>
33
+#include <queue>
34
+#include <thread>
35
+#include <vector>
36
+#include <chrono>
37
+
38
+// Plugin
39
+#include "plugin.h"
40
+#include "amf.h"
41
+#include "api-base.h"
42
+
43
+//////////////////////////////////////////////////////////////////////////
44
+// Code
45
+//////////////////////////////////////////////////////////////////////////
46
+
47
+namespace Plugin {
48
+   namespace AMD {
49
+       // Internal Properties
50
+       enum VCEEncoderType {
51
+           VCEEncoderType_AVC,     // Advanced Video Coding
52
+           VCEEncoderType_SVC,     // Scalable Video Coding
53
+           VCEEncoderType_HEVC,    // High-Efficiency Video Coding (Discovered in amfrt64.dll)
54
+       };
55
+       enum VCEMemoryType {
56
+           VCEMemoryType_Host,         // Host-Managed Memory
57
+           VCEMemoryType_DirectX9,     // DirectX9
58
+           VCEMemoryType_DirectX11,    // DirectX11
59
+           VCEMemoryType_OpenGL,       // OpenGL
60
+       };
61
+       enum VCEColorFormat {
62
+           // 4:2:0 Formats
63
+           VCEColorFormat_NV12,    // NV12
64
+           VCEColorFormat_I420,    // YUV 4:2:0
65
+           // 4:2:2 Formats
66
+           VCEColorFormat_YUY2,
67
+           // Uncompressed
68
+           VCEColorFormat_BGRA,    // ARGB
69
+           VCEColorFormat_RGBA,    // RGBA
70
+           // Other
71
+           VCEColorFormat_GRAY,
72
+       };
73
+       enum VCEColorProfile {
74
+           VCEColorProfile_601,
75
+           VCEColorProfile_709,
76
+           VCEColorProfile_2020, // HDR
77
+       };
78
+
79
+       // Static Properties
80
+       enum VCEUsage {
81
+           VCEUsage_Transcoding,
82
+           VCEUsage_UltraLowLatency,
83
+           VCEUsage_LowLatency,
84
+           VCEUsage_Webcam,            // For SVC
85
+       };
86
+       enum VCEQualityPreset {
87
+           VCEQualityPreset_Speed,
88
+           VCEQualityPreset_Balanced,
89
+           VCEQualityPreset_Quality,
90
+       };
91
+       enum VCEProfile {
92
+           VCEProfile_Baseline = 66,
93
+           VCEProfile_Main = 77,
94
+           VCEProfile_High = 100,
95
+           VCEProfile_ConstrainedBaseline = 256,
96
+           VCEProfile_ConstrainedHigh = 257
97
+       };
98
+       enum VCEProfileLevel {
99
+           VCEProfileLevel_Automatic = 0,
100
+           VCEProfileLevel_10 = 10,
101
+           VCEProfileLevel_11,
102
+           VCEProfileLevel_12,
103
+           VCEProfileLevel_13,
104
+           VCEProfileLevel_20 = 20,
105
+           VCEProfileLevel_21,
106
+           VCEProfileLevel_22,
107
+           VCEProfileLevel_30 = 30,
108
+           VCEProfileLevel_31,
109
+           VCEProfileLevel_32,
110
+           VCEProfileLevel_40 = 40,
111
+           VCEProfileLevel_41,
112
+           VCEProfileLevel_42,
113
+           VCEProfileLevel_50 = 50,
114
+           VCEProfileLevel_51,
115
+           VCEProfileLevel_52,
116
+           VCEProfileLevel_60 = 60,
117
+           VCEProfileLevel_61,
118
+           VCEProfileLevel_62,
119
+       };
120
+       enum VCEScanType {
121
+           VCEScanType_Progressive,
122
+           VCEScanType_Interlaced,
123
+       };
124
+       enum VCECodingType {
125
+           VCECodingType_Default = 0,
126
+           VCECodingType_CABAC = 1,
127
+           VCECodingType_CALVC = 2,
128
+       };
129
+
130
+       // Dynamic Properties
131
+       enum VCERateControlMethod {
132
+           VCERateControlMethod_ConstantQP,
133
+           VCERateControlMethod_ConstantBitrate,
134
+           VCERateControlMethod_VariableBitrate_PeakConstrained,
135
+           VCERateControlMethod_VariableBitrate_LatencyConstrained,
136
+       };
137
+       enum VCEBFramePattern {
138
+           VCEBFramePattern_None,
139
+           VCEBFramePattern_One,
140
+           VCEBFramePattern_Two,
141
+           VCEBFramePattern_Three,
142
+       };
143
+
144
+       // Experimental
145
+       enum VCESliceMode {
146
+           VCESliceMode_Horizontal = 1,
147
+           VCESliceMode_Vertical = 2
148
+       };
149
+       enum VCESliceControlMode {
150
+           VCESliceControlMode_Off,
151
+           VCESliceControlMode_Macroblock = 1, // AMF_VIDEO_ENCODER_SLICE_CTRL_MODE_MB
152
+           VCESliceControlMode_Invalid,
153
+           VCESliceControlMode_Macroblock_Row = 3 // AMF_VIDEO_ENCODER_SLICE_CTRL_MODE_MB_ROW
154
+       };
155
+
156
+
157
+
158
+       class VCEEncoder {
159
+           #pragma region Initializer & Finalizer
160
+           public:
161
+           VCEEncoder(
162
+               VCEEncoderType p_Type,
163
+               std::string p_VideoAPI,
164
+               uint64_t p_VideoAdapterId,
165
+               bool p_OpenCL,
166
+               VCEColorFormat p_SurfaceFormat = VCEColorFormat_NV12
167
+           );
168
+           ~VCEEncoder();
169
+           #pragma endregion Initializer & Finalizer
170
+
171
+           public:
172
+           void Start();
173
+           void Restart();
174
+           void Stop();
175
+           bool IsStarted();
176
+
177
+           bool SendInput(struct encoder_frame* frame);
178
+           bool GetOutput(struct encoder_packet* packet, bool* received_packet);
179
+           bool GetExtraData(uint8_t**& data, size_t*& size);
180
+           void GetVideoInfo(struct video_scale_info*& vsi);
181
+
182
+           #pragma region Properties
183
+           public:
184
+           void LogProperties();
185
+
186
+           // Static
187
+
188
+           #pragma region Startup Properties
189
+           // Set which Usage preset to use.
190
+           // Changing this will also change a lot of other properties.
191
+           void SetUsage(VCEUsage usage);
192
+           VCEUsage GetUsage();
193
+
194
+           // Set which Quality Preset AMF should use.
195
+           // Affects the quality of the output.
196
+           void SetQualityPreset(VCEQualityPreset preset);
197
+           VCEQualityPreset GetQualityPreset();
198
+
199
+           // Set the Profile the output should have.
200
+           void SetProfile(VCEProfile profile);
201
+           VCEProfile GetProfile();
202
+
203
+           // Set the Profile Level the output should have.
204
+           void SetProfileLevel(VCEProfileLevel level);
205
+           VCEProfileLevel GetProfileLevel();
206
+           #pragma endregion Startup Properties
207
+
208
+           #pragma region Frame Properties
209
+           // Set which Color Profile the input frame is.
210
+           void SetColorProfile(VCEColorProfile profile);
211
+           VCEColorProfile GetColorProfile();
212
+
213
+           // Set if the input frame is in full color range.
214
+           void SetFullRangeColorEnabled(bool enabled);
215
+           bool IsFullRangeColorEnabled();
216
+
217
+           // Resolution for the input and output.
218
+           void SetResolution(uint32_t width, uint32_t height);
219
+           std::pair<uint32_t, uint32_t> GetResolution();
220
+
221
+           // Framerate of the input and output.
222
+           void SetFrameRate(uint32_t num, uint32_t den);
223
+           std::pair<uint32_t, uint32_t> GetFrameRate();
224
+
225
+           // Scanning method for input (and output?).
226
+           void SetScanType(VCEScanType scanType);
227
+           VCEScanType GetScanType();
228
+           #pragma endregion Frame Properties
229
+
230
+           // Dynamic
231
+
232
+           #pragma region Rate Control
233
+           /*  Selects the rate control method:
234
+            *  - CQP - Constrained QP,
235
+            *  - CBR - Constant Bitrate,
236
+            *  - VBR - Peak Constrained VBR,
237
+            *  - VBR_LAT - Latency Constrained VBR
238
+            *
239
+            *  Remarks:
240
+            *  - 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].
241
+            *  - 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).
242
+           **/
243
+           void SetRateControlMethod(VCERateControlMethod method);
244
+           VCERateControlMethod GetRateControlMethod();
245
+
246
+           /*  Sets the target bitrate */
247
+           void SetTargetBitrate(uint32_t bitrate);
248
+           uint32_t GetTargetBitrate();
249
+
250
+           /*  Sets the peak bitrate */
251
+           void SetPeakBitrate(uint32_t bitrate);
252
+           uint32_t GetPeakBitrate();
253
+
254
+           /*  Sets the minimum QP */
255
+           void SetMinimumQP(uint8_t qp);
256
+           uint8_t GetMinimumQP();
257
+
258
+           /*  Sets the maximum QP */
259
+           void SetMaximumQP(uint8_t qp);
260
+           uint8_t GetMaximumQP();
261
+
262
+           // Set the fixed QP value for I-Frames.
263
+           void SetIFrameQP(uint8_t qp);
264
+           uint8_t GetIFrameQP();
265
+
266
+           // Set the fixed QP value for P-Frames.
267
+           void SetPFrameQP(uint8_t qp);
268
+           uint8_t GetPFrameQP();
269
+
270
+           // Set the fixed QP value for B-Frames.
271
+           void SetBFrameQP(uint8_t qp);
272
+           uint8_t GetBFrameQP();
273
+
274
+           // Set the Video Buffer Verifier (VBV) size in bits per second (bps).
275
+           void SetVBVBufferSize(uint32_t size);
276
+           // Set the Video Buffer Verifier (VBV) size using a strictness constraint.
277
+           void SetVBVBufferAutomatic(double_t strictness);
278
+           uint32_t GetVBVBufferSize();
279
+
280
+           /*  Sets the initial VBV Buffer Fullness */
281
+           void SetInitialVBVBufferFullness(double_t fullness);
282
+           double_t GetInitialVBVBufferFullness();
283
+
284
+           /*  Enables/Disables filler data */
285
+           void SetFillerDataEnabled(bool enabled);
286
+           bool IsFillerDataEnabled();
287
+
288
+           /*  Enables skip frame for rate control */
289
+           void SetFrameSkippingEnabled(bool enabled);
290
+           bool IsFrameSkippingEnabled();
291
+
292
+           /*  Enables/Disables constraints on QP variation within a picture to meet HRD requirement(s) */
293
+           void SetEnforceHRDRestrictionsEnabled(bool enforce);
294
+           bool IsEnforceHRDRestrictionsEnabled();
295
+           #pragma endregion Rate Control
296
+
297
+           #pragma region Picture Control
298
+           // Set the Instantaneous-Decoder-Refresh (IDR) Period in frames.
299
+           void SetIDRPeriod(uint32_t period);
300
+           uint32_t GetIDRPeriod();
301
+
302
+           #pragma region B-Frames
303
+           /*  Sets the number of consecutive B-Frames. BFramesPattern = 0 indicates that B-Frames are not used */
304
+           void SetBFramePattern(VCEBFramePattern pattern);
305
+           VCEBFramePattern GetBFramePattern();
306
+
307
+           /* Selects the delta QP of non-reference B-Frames with respect to the last non-B-Frame */
308
+           void SetBFrameDeltaQP(int8_t qp);
309
+           int8_t GetBFrameDeltaQP();
310
+
311
+           /*  Enables or disables using B-Frames as references */
312
+           void SetBFrameReferenceEnabled(bool enabled);
313
+           bool IsBFrameReferenceEnabled();
314
+
315
+           /* Selects delta QP of reference B-Frames with respect to the last non-B-Frame */
316
+           void SetBFrameReferenceDeltaQP(int8_t qp);
317
+           int8_t GetBFrameReferenceDeltaQP();
318
+           #pragma endregion B-Frames
319
+           #pragma endregion Picture Control
320
+
321
+           #pragma region Miscellaneous
322
+           /*  Turns on/off the Deblocking Filter */
323
+           void SetDeblockingFilterEnabled(bool enabled);
324
+           bool IsDeblockingFilterEnabled();
325
+
326
+           #pragma region Motion Estimation
327
+           /* Turns on/off half-pixel motion estimation */
328
+           void SetHalfPixelMotionEstimationEnabled(bool enabled);
329
+           bool IsHalfPixelMotionEstimationEnabled();
330
+
331
+           /* Turns on/off quarter-pixel motion estimation */
332
+           void SetQuarterPixelMotionEstimationEnabled(bool enabled);
333
+           bool IsQuarterPixelMotionEstimationEnabled();
334
+           #pragma endregion Motion Estimation
335
+           #pragma endregion Miscellaneous
336
+
337
+           #pragma region Experimental Properties
338
+           // Get the maximum amount of MBps the encoder can output.
339
+           uint32_t GetMaxMBPerSec();
340
+
341
+           /* Coding Type */
342
+           void SetCodingType(VCECodingType type);
343
+           VCECodingType GetCodingType();
344
+
345
+           void SetWaitForTaskEnabled(bool enabled);
346
+           bool IsWaitForTaskEnabled();
347
+
348
+           // Preanalysis Pass is AMDs version of Two-Pass hardware encoding.
349
+           void SetPreAnalysisPassEnabled(bool enabled);
350
+           bool IsPreAnalysisPassEnabled();
351
+
352
+           // VBAQ = Variable Bitrate Average Quality?
353
+           // - EanbleVBAQ (bool)
354
+           void SetVBAQEnabled(bool enabled);
355
+           bool IsVBAQEnabled();
356
+
357
+           /*  Sets the headers insertion spacing */
358
+           void SetHeaderInsertionSpacing(uint32_t spacing); // Similar to IDR Period, spacing (in frames) between headers.
359
+           uint32_t GetHeaderInsertionSpacing();
360
+
361
+           /*  The number of long-term references controlled by the user.
362
+           *
363
+           *   Remarks:
364
+           *  - When == 0, the encoder may or may not use LTRs during encoding.
365
+           *   - When >0, the user has control over all LTR.
366
+           *   - With user control of LTR, B-Frames and Intra-refresh features are not supported.
367
+           *   - The actual maximum number of LTRs allowed depends on H.264 Annex A Table A-1 Level limits, which defines dependencies between the H.264 Level number, encoding resolution, and DPB size. The DPB size limit impacts the maximum number of LTR allowed.
368
+           **/
369
+           void SetMaximumLongTermReferenceFrames(uint32_t maximumLTRFrames);  // Long-Term Reference Frames. If 0, Encoder decides, if non-0 B-Frames and Intra-Refresh are not supported.
370
+           uint32_t GetMaximumLongTermReferenceFrames();
371
+
372
+           /*  Sets Maximum AU Size in bits */
373
+           void SetMaximumAccessUnitSize(uint32_t size);
374
+           uint32_t GetMaximumAccessUnitSize();
375
+
376
+           void SetMaximumReferenceFrames(uint32_t frameCount);
377
+           uint32_t GetMaximumReferenceFrames();
378
+
379
+           void SetAspectRatio(uint32_t x, uint32_t y);
380
+           std::pair<uint32_t, uint32_t> GetAspectRatio();
381
+
382
+           #pragma region Group of Pictures
383
+           void SetGOPSize(uint32_t gopSize);
384
+           uint32_t GetGOPSize();
385
+
386
+           void SetGOPAlignmentEnabled(bool enabled);
387
+           bool IsGOPAlignementEnabled();
388
+           #pragma endregion Group of Pictures
389
+
390
+           #pragma region Intra Refresh
391
+           // Macroblocks per Intra-Refresh Slot
392
+           // Intra-Refresh Coding
393
+           void SetIntraRefreshMacroblocksPerSlot(uint32_t macroblocks);
394
+           uint32_t GetIntraRefreshMacroblocksPerSlot();
395
+
396
+           // - IntraRefreshNumOfStripes (0 - INT_MAX)
397
+           // Intra-Refresh Coding
398
+           void SetIntraRefreshNumberOfStripes(uint32_t stripes);
399
+           uint32_t GetIntraRefreshNumberOfStripes();
400
+           #pragma endregion Intra Refresh
401
+
402
+           #pragma region Slicing
403
+           /*  Sets the number of slices per frame */
404
+           void SetSlicesPerFrame(uint32_t slices);
405
+           uint32_t GetSlicesPerFrame();
406
+
407
+           // - SliceMode (1 - 2, Default is 1)
408
+           void SetSliceMode(VCESliceMode mode);
409
+           VCESliceMode GetSliceMode();
410
+
411
+           // - MaxSliceSize (1 - INT_MAX)
412
+           void SetMaximumSliceSize(uint32_t size);
413
+           uint32_t GetMaximumSliceSize();
414
+
415
+           // - SliceControlMode (0 - 3)
416
+           void SetSliceControlMode(VCESliceControlMode mode);
417
+           VCESliceControlMode GetSliceControlMode();
418
+
419
+           // - SliceControlSize (0 - INT_MAX)
420
+           void SetSliceControlSize(uint32_t size);
421
+           uint32_t GetSliceControlSize();
422
+           #pragma endregion Slicing
423
+
424
+           // More:
425
+           // - CodecId (H264 = 5, H264SVC = 8, 2xUNKNOWN)
426
+           // - EngineType (Auto = 0, DX9 = 1, DX11 = 2, XVBA = 3)
427
+           // - ConstraintSetFlags (0 - 255, 1 byte bitset?)
428
+           // - LowLatencyInternal (bool)
429
+           // - CommonLowLatencyInternal (bool)
430
+           // - UniqueInstance (0 - INT_MAX)
431
+           // - MultiInstanceMode (bool)
432
+           // - MultiInstanceCurrentQueue (0 - 1)
433
+           // - InstanceId (-1 - [# of Streams - 1])
434
+           // - EncoderMaxInstances (1 - [# of Instances])
435
+           #pragma endregion Experimental Properties
436
+
437
+           #pragma endregion Properties
438
+
439
+           // Threading
440
+           private:
441
+           static void InputThreadMain(Plugin::AMD::VCEEncoder* p_this);
442
+           void InputThreadLogic();
443
+           static void OutputThreadMain(Plugin::AMD::VCEEncoder* p_this);
444
+           void OutputThreadLogic();
445
+           inline amf::AMFSurfacePtr CreateSurfaceFromFrame(struct encoder_frame*& frame);
446
+
447
+           #pragma region Members
448
+           private:
449
+           // AMF Data References
450
+           std::shared_ptr<Plugin::AMD::AMF> m_AMF;
451
+           amf::AMFFactory* m_AMFFactory;
452
+           amf::AMFContextPtr m_AMFContext;
453
+           amf::AMFComponentPtr m_AMFConverter;
454
+           amf::AMFComponentPtr m_AMFEncoder;
455
+           amf::AMFComputePtr m_AMFCompute;
456
+
457
+           // API References
458
+           std::shared_ptr<Plugin::API::Base> m_API;
459
+           Plugin::API::Adapter m_APIAdapter;
460
+           void* m_APIInstance;
461
+
462
+           // Static Buffers
463
+           std::vector<uint8_t> m_PacketDataBuffer;
464
+           std::vector<uint8_t> m_ExtraDataBuffer;
465
+
466
+           // Structured Queue
467
+           struct {
468
+               std::queue<amf::AMFSurfacePtr> queue;
469
+
470
+               // Threading
471
+               std::thread thread;
472
+               std::mutex mutex;
473
+               std::condition_variable condvar;
474
+               std::mutex queuemutex;
475
+           } m_Input;
476
+           struct {
477
+               std::queue<amf::AMFDataPtr> queue;
478
+
479
+               // Threading
480
+               std::thread thread;
481
+               std::mutex mutex;
482
+               std::condition_variable condvar;
483
+               std::mutex queuemutex;
484
+           } m_Output;
485
+
486
+           // Internal Properties
487
+           VCEEncoderType m_EncoderType;
488
+           VCEMemoryType m_MemoryType;
489
+           bool m_OpenCL;
490
+           VCEColorFormat m_ColorFormat;
491
+           bool m_Flag_IsStarted,
492
+               m_Flag_FirstFrameSubmitted,
493
+               m_Flag_FirstFrameReceived;
494
+           std::pair<uint32_t, uint32_t> m_FrameSize,
495
+               m_FrameRate;
496
+           double_t m_FrameRateDivisor,
497
+               m_FrameRateReverseDivisor;
498
+           size_t m_InputQueueLimit,
499
+               m_InputQueueLastSize;
500
+           uint32_t m_TimerPeriod;
501
+           VCEColorProfile m_ColorProfile;
502
+           std::chrono::time_point<std::chrono::high_resolution_clock> m_LastQueueWarnMessageTime;
503
+
504
+           #pragma endregion Members
505
+       };
506
+   }
507
+}
508
\ No newline at end of file
509
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/amf.h Changed
2
 
1
(renamed from plugins/enc-amf/Include/amd-amf.h)
2
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Include/api-base.h -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/api-base.h Changed
107
 
1
@@ -27,61 +27,67 @@
2
 // Includes
3
 //////////////////////////////////////////////////////////////////////////
4
 #include "plugin.h"
5
+
6
 #include <vector>
7
+#include <map>
8
 
9
 //////////////////////////////////////////////////////////////////////////
10
 // Code
11
 //////////////////////////////////////////////////////////////////////////
12
 namespace Plugin {
13
    namespace API {
14
-       struct Device {
15
-           std::string Name;
16
-           std::string UniqueId;
17
-
18
-           Device();
19
-           Device(std::string Name, std::string UniqueId);
20
-           ~Device();
21
-
22
-
23
-           friend bool operator<(const Plugin::API::Device& left, const Plugin::API::Device& right);
24
-           friend bool operator>(const Plugin::API::Device& left, const Plugin::API::Device& right);
25
-           friend bool operator<=(const Plugin::API::Device& left, const Plugin::API::Device& right);
26
-           friend bool operator>=(const Plugin::API::Device& left, const Plugin::API::Device& right);
27
-
28
-           friend bool operator==(const Plugin::API::Device& left, const Plugin::API::Device& right);
29
-           friend bool operator!=(const Plugin::API::Device& left, const Plugin::API::Device& right);
30
-       };
31
-
32
        enum APIType {
33
-           APIType_Base,
34
+           APIType_Host,
35
            APIType_Direct3D9,
36
            APIType_Direct3D11,
37
            APIType_OpenGL,
38
        };
39
 
40
-       class APIBase {
41
-           public:
42
-           static std::vector<Plugin::API::Device> EnumerateDevices();
43
-           static Plugin::API::Device GetDeviceForUniqueId(std::string uniqueId);
44
+       struct Adapter {
45
+           int32_t idLow, idHigh;
46
+           std::string Name;
47
 
48
-           static Plugin::API::APIType GetBestAvailableAPI();
49
-           static std::unique_ptr<Plugin::API::APIBase>
50
-               CreateBestAvailableAPI(Plugin::API::Device device);
51
+           Adapter() : idLow(0), idHigh(0), Name("Invalid Device") {}
52
+           Adapter(int32_t idLow, int32_t idHigh, std::string Name) : idLow(idLow), idHigh(idHigh), Name(Name) {}
53
 
54
-           APIBase();
55
-           APIBase(Device device);
56
-           virtual ~APIBase();
57
+           friend bool operator<(const Plugin::API::Adapter& left, const Plugin::API::Adapter& right);
58
+           friend bool operator>(const Plugin::API::Adapter& left, const Plugin::API::Adapter& right);
59
+           friend bool operator<=(const Plugin::API::Adapter& left, const Plugin::API::Adapter& right);
60
+           friend bool operator>=(const Plugin::API::Adapter& left, const Plugin::API::Adapter& right);
61
 
62
-           Plugin::API::Device GetDevice();
63
+           friend bool operator==(const Plugin::API::Adapter& left, const Plugin::API::Adapter& right);
64
+           friend bool operator!=(const Plugin::API::Adapter& left, const Plugin::API::Adapter& right);
65
+       };
66
+
67
+       class Base {
68
+           //////////////////////////////////////////////////////////////////////////
69
+           // API Index
70
+           //////////////////////////////////////////////////////////////////////////
71
+           public:
72
+           static void Initialize();
73
+
74
+           static size_t GetAPICount();
75
+           static std::shared_ptr<Base> GetAPIInstance(size_t index);
76
+           static std::string GetAPIName(size_t index);
77
+           static std::shared_ptr<Base> GetAPIByName(std::string name);
78
+           static std::vector<std::shared_ptr<Base>> EnumerateAPIs();
79
+           static std::vector<std::string> EnumerateAPINames();
80
+
81
+           //////////////////////////////////////////////////////////////////////////
82
+           // API
83
+           //////////////////////////////////////////////////////////////////////////
84
+           public:
85
+           virtual std::string GetName() = 0;
86
+           virtual APIType GetType() = 0;
87
 
88
-           virtual Plugin::API::APIType GetType();
89
-           virtual void* GetContext();
90
-           
91
-           protected:
92
-           Plugin::API::APIType myType;
93
+           virtual std::vector<Adapter> EnumerateAdapters() = 0;
94
+           virtual Adapter GetAdapterById(uint32_t idLow, uint32_t idHigh) = 0;
95
+           virtual Adapter GetAdapterByName(std::string name) = 0;
96
 
97
-           private:
98
-           Plugin::API::Device myDevice;
99
+           virtual void* CreateInstanceOnAdapter(Adapter adapter) = 0;
100
+           virtual Adapter GetAdapterForInstance(void* instance) = 0;
101
+           virtual void* GetContextFromInstance(void* instance) = 0;
102
+           virtual void DestroyInstance(void* instance) = 0;
103
        };
104
    }
105
 }
106
\ No newline at end of file
107
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Include/api-d3d11.h -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/api-d3d11.h Changed
49
 
1
@@ -23,33 +23,30 @@
2
 */
3
 
4
 #pragma once
5
-#ifdef _WIN32
6
+
7
 //////////////////////////////////////////////////////////////////////////
8
 // Includes
9
 //////////////////////////////////////////////////////////////////////////
10
 #include "api-base.h"
11
 
12
-#include <d3d11.h>
13
-
14
 //////////////////////////////////////////////////////////////////////////
15
 // Code
16
 //////////////////////////////////////////////////////////////////////////
17
+
18
 namespace Plugin {
19
    namespace API {
20
-       class Direct3D11 : public APIBase {
21
-           public:
22
-           static std::vector<Plugin::API::Device> EnumerateDevices();
23
-           static Plugin::API::Device GetDeviceForUniqueId(std::string uniqueId);
24
-
25
-           Direct3D11(Device device);
26
-           ~Direct3D11();
27
-
28
-           virtual void* GetContext() override;
29
-
30
-           private:
31
-           ID3D11Device* pDevice;
32
-           ID3D11DeviceContext* pDeviceContext;
33
+       class Direct3D11 : public Base {
34
+           virtual std::string GetName() override;
35
+           virtual APIType GetType() override;
36
+
37
+           virtual std::vector<Adapter> EnumerateAdapters() override;
38
+           virtual Adapter GetAdapterById(uint32_t idLow, uint32_t idHigh) override;
39
+           virtual Adapter GetAdapterByName(std::string name) override;
40
+
41
+           virtual void* CreateInstanceOnAdapter(Adapter adapter) override;
42
+           virtual Adapter GetAdapterForInstance(void* pInstance) override;
43
+           virtual void* GetContextFromInstance(void* pInstance) override;
44
+           virtual void DestroyInstance(void* pInstance) override;
45
        };
46
    }
47
 }
48
-#endif
49
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Include/api-d3d9.h -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/api-d3d9.h Changed
51
 
1
@@ -23,35 +23,30 @@
2
 */
3
 
4
 #pragma once
5
-#ifdef _WIN32
6
+
7
 //////////////////////////////////////////////////////////////////////////
8
 // Includes
9
 //////////////////////////////////////////////////////////////////////////
10
 #include "api-base.h"
11
 
12
-#define D3D_DEBUG_INFO
13
-#include <d3d9.h>
14
-#pragma comment(lib, "d3d9.lib")
15
-
16
 //////////////////////////////////////////////////////////////////////////
17
 // Code
18
 //////////////////////////////////////////////////////////////////////////
19
+
20
 namespace Plugin {
21
    namespace API {
22
-       class Direct3D9 : public APIBase {
23
-           public:
24
-           static std::vector<Plugin::API::Device> EnumerateDevices();
25
-           static Plugin::API::Device GetDeviceForUniqueId(std::string uniqueId);
26
-
27
-           Direct3D9(Device device);
28
-           ~Direct3D9();
29
-
30
-           virtual void* GetContext() override;
31
-
32
-           private:
33
-           IDirect3D9* pDirect3D;
34
-           IDirect3DDevice9* pDirect3DDevice;
35
+       class Direct3D9 : public Base {
36
+           virtual std::string GetName() override;
37
+           virtual APIType GetType() override;
38
+
39
+           virtual std::vector<Adapter> EnumerateAdapters() override;
40
+           virtual Adapter GetAdapterById(uint32_t idLow, uint32_t idHigh);
41
+           virtual Adapter GetAdapterByName(std::string name);
42
+
43
+           virtual void* CreateInstanceOnAdapter(Adapter adapter) override;
44
+           virtual Adapter GetAdapterForInstance(void* pInstance) override;
45
+           virtual void* GetContextFromInstance(void* pInstance) override;
46
+           virtual void DestroyInstance(void* pInstance) override;
47
        };
48
    }
49
 }
50
-#endif
51
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/api-host.h Added
54
 
1
@@ -0,0 +1,52 @@
2
+/*
3
+MIT License
4
+
5
+Copyright (c) 2016 Michael Fabian Dirks
6
+
7
+Permission is hereby granted, free of charge, to any person obtaining a copy
8
+of this software and associated documentation files (the "Software"), to deal
9
+in the Software without restriction, including without limitation the rights
10
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+copies of the Software, and to permit persons to whom the Software is
12
+furnished to do so, subject to the following conditions:
13
+
14
+The above copyright notice and this permission notice shall be included in all
15
+copies or substantial portions of the Software.
16
+
17
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+SOFTWARE.
24
+*/
25
+
26
+#pragma once
27
+
28
+//////////////////////////////////////////////////////////////////////////
29
+// Includes
30
+//////////////////////////////////////////////////////////////////////////
31
+#include "api-base.h"
32
+
33
+//////////////////////////////////////////////////////////////////////////
34
+// Code
35
+//////////////////////////////////////////////////////////////////////////
36
+
37
+namespace Plugin {
38
+   namespace API {
39
+       class Host : public Base {
40
+           virtual std::string GetName() override;
41
+           virtual APIType GetType() override;
42
+
43
+           virtual std::vector<Adapter> EnumerateAdapters() override;
44
+           virtual Adapter GetAdapterById(uint32_t idLow, uint32_t idHigh);
45
+           virtual Adapter GetAdapterByName(std::string name);
46
+
47
+           virtual void* CreateInstanceOnAdapter(Adapter adapter) override;
48
+           virtual Adapter GetAdapterForInstance(void* pInstance) override;
49
+           virtual void* GetContextFromInstance(void* pInstance) override;
50
+           virtual void DestroyInstance(void* pInstance) override;
51
+       };
52
+   }
53
+}
54
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/api-opengl.h Added
54
 
1
@@ -0,0 +1,52 @@
2
+/*
3
+MIT License
4
+
5
+Copyright (c) 2016 Michael Fabian Dirks
6
+
7
+Permission is hereby granted, free of charge, to any person obtaining a copy
8
+of this software and associated documentation files (the "Software"), to deal
9
+in the Software without restriction, including without limitation the rights
10
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+copies of the Software, and to permit persons to whom the Software is
12
+furnished to do so, subject to the following conditions:
13
+
14
+The above copyright notice and this permission notice shall be included in all
15
+copies or substantial portions of the Software.
16
+
17
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+SOFTWARE.
24
+*/
25
+
26
+#pragma once
27
+
28
+//////////////////////////////////////////////////////////////////////////
29
+// Includes
30
+//////////////////////////////////////////////////////////////////////////
31
+#include "api-base.h"
32
+
33
+//////////////////////////////////////////////////////////////////////////
34
+// Code
35
+//////////////////////////////////////////////////////////////////////////
36
+
37
+namespace Plugin {
38
+   namespace API {
39
+       class OpenGL : public Base {
40
+           virtual std::string GetName() override;
41
+           virtual APIType GetType() override;
42
+
43
+           virtual std::vector<Adapter> EnumerateAdapters() override;
44
+           virtual Adapter GetAdapterById(uint32_t idLow, uint32_t idHigh);
45
+           virtual Adapter GetAdapterByName(std::string name);
46
+
47
+           virtual void* CreateInstanceOnAdapter(Adapter adapter) override;
48
+           virtual Adapter GetAdapterForInstance(void* instance) override;
49
+           virtual void* GetContextFromInstance(void* instance) override;
50
+           virtual void DestroyInstance(void* instance) override;
51
+       };
52
+   }
53
+}
54
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Include/enc-h264.h -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/enc-h264.h Changed
167
 
1
@@ -28,8 +28,155 @@
2
 //////////////////////////////////////////////////////////////////////////
3
 // Plugin
4
 #include "plugin.h"
5
-#include "amd-amf-vce.h"
6
-#include "amd-amf-vce-capabilities.h"
7
+#include "amf-capabilities.h"
8
+#include "amf-h264.h"
9
+
10
+//////////////////////////////////////////////////////////////////////////
11
+// Defines - Translation Strings
12
+//////////////////////////////////////////////////////////////////////////
13
+
14
+// Presets
15
+#define AMF_H264_PRESET                                        TEXT_AMF_H264("Preset")
16
+#define AMF_H264_PRESET_RESETTODEFAULTS                        TEXT_AMF_H264("Preset.ResetToDefaults")
17
+#define AMF_H264_PRESET_RECORDING                          TEXT_AMF_H264("Preset.Recording")
18
+#define AMF_H264_PRESET_HIGHQUALITY                            TEXT_AMF_H264("Preset.HighQuality")
19
+#define AMF_H264_PRESET_INDISTINGUISHABLE                  TEXT_AMF_H264("Preset.Indistinguishable")
20
+#define AMF_H264_PRESET_LOSSLESS                           TEXT_AMF_H264("Preset.Lossless")
21
+#define AMF_H264_PRESET_TWITCH                             TEXT_AMF_H264("Preset.Twitch")
22
+#define AMF_H264_PRESET_YOUTUBE                                TEXT_AMF_H264("Preset.YouTube")
23
+
24
+// Startup Properties
25
+#define AMF_H264_USAGE                                     TEXT_AMF_H264("Usage")
26
+#define AMF_H264_USAGE_DESCRIPTION                         TEXT_AMF_H264("Usage.Description")
27
+#define AMF_H264_USAGE_TRANSCODING                         TEXT_AMF_H264("Usage.Transcoding")
28
+#define AMF_H264_USAGE_ULTRALOWLATENCY                     TEXT_AMF_H264("Usage.UltraLowLatency")
29
+#define AMF_H264_USAGE_LOWLATENCY                          TEXT_AMF_H264("Usage.LowLatency")
30
+#define AMF_H264_USAGE_WEBCAM                              TEXT_AMF_H264("Usage.Webcam")
31
+#define AMF_H264_QUALITY_PRESET                                TEXT_AMF_H264("QualityPreset")
32
+#define AMF_H264_QUALITY_PRESET_DESCRIPTION                    TEXT_AMF_H264("QualityPreset.Description")
33
+#define AMF_H264_QUALITY_PRESET_SPEED                      TEXT_AMF_H264("QualityPreset.Speed")
34
+#define AMF_H264_QUALITY_PRESET_BALANCED                   TEXT_AMF_H264("QualityPreset.Balanced")
35
+#define AMF_H264_QUALITY_PRESET_QUALITY                        TEXT_AMF_H264("QualityPreset.Quality")
36
+#define AMF_H264_PROFILE                                   TEXT_AMF_H264("Profile")
37
+#define AMF_H264_PROFILE_DESCRIPTION                       TEXT_AMF_H264("Profile.Description")
38
+#define AMF_H264_PROFILELEVEL                              TEXT_AMF_H264("ProfileLevel")
39
+#define AMF_H264_PROFILELEVEL_DESCRIPTION                  TEXT_AMF_H264("ProfileLevel.Description")
40
+
41
+// Rate Control Properties
42
+#define AMF_H264_RATECONTROLMETHOD                         TEXT_AMF_H264("RateControlMethod")
43
+#define AMF_H264_RATECONTROLMETHOD_DESCRIPTION             TEXT_AMF_H264("RateControlMethod.Description")
44
+#define AMF_H264_RATECONTROLMETHOD_CQP                     TEXT_AMF_H264("RateControlMethod.CQP")
45
+#define AMF_H264_RATECONTROLMETHOD_CBR                     TEXT_AMF_H264("RateControlMethod.CBR")
46
+#define AMF_H264_RATECONTROLMETHOD_VBR                     TEXT_AMF_H264("RateControlMethod.VBR.Peak")
47
+#define AMF_H264_RATECONTROLMETHOD_VBR_LAT                 TEXT_AMF_H264("RateControlMethod.VBR.Latency")
48
+#define AMF_H264_BITRATE_TARGET                                TEXT_AMF_H264("Bitrate.Target")
49
+#define AMF_H264_BITRATE_TARGET_DESCRIPTION                    TEXT_AMF_H264("Bitrate.Target.Description")
50
+#define AMF_H264_BITRATE_PEAK                              TEXT_AMF_H264("Bitrate.Peak")
51
+#define AMF_H264_BITRATE_PEAK_DESCRIPTION                  TEXT_AMF_H264("Bitrate.Peak.Description")
52
+#define AMF_H264_QP_MINIMUM                                    TEXT_AMF_H264("QP.Minimum")
53
+#define AMF_H264_QP_MINIMUM_DESCRIPTION                        TEXT_AMF_H264("QP.Minimum.Description")
54
+#define AMF_H264_QP_MAXIMUM                                    TEXT_AMF_H264("QP.Maximum")
55
+#define AMF_H264_QP_MAXIMUM_DESCRIPTION                        TEXT_AMF_H264("QP.Maximum.Description")
56
+#define AMF_H264_QP_IFRAME                                 TEXT_AMF_H264("QP.IFrame")
57
+#define AMF_H264_QP_IFRAME_DESCRIPTION                     TEXT_AMF_H264("QP.IFrame.Description")
58
+#define AMF_H264_QP_PFRAME                                 TEXT_AMF_H264("QP.PFrame")
59
+#define AMF_H264_QP_PFRAME_DESCRIPTION                     TEXT_AMF_H264("QP.PFrame.Description")
60
+#define AMF_H264_QP_BFRAME                                 TEXT_AMF_H264("QP.BFrame")
61
+#define AMF_H264_QP_BFRAME_DESCRIPTION                     TEXT_AMF_H264("QP.BFrame.Description")
62
+#define AMF_H264_VBVBUFFER                                 TEXT_AMF_H264("VBVBuffer")
63
+#define AMF_H264_VBVBUFFER_DESCRIPTION                     TEXT_AMF_H264("VBVBuffer.Description")
64
+#define AMF_H264_VBVBUFFER_STRICTNESS                      TEXT_AMF_H264("VBVBuffer.Strictness")
65
+#define AMF_H264_VBVBUFFER_STRICTNESS_DESCRIPTION          TEXT_AMF_H264("VBVBuffer.Strictness.Description")
66
+#define AMF_H264_VBVBUFFER_SIZE                                TEXT_AMF_H264("VBVBuffer.Size")
67
+#define AMF_H264_VBVBUFFER_SIZE_DESCRIPTION                    TEXT_AMF_H264("VBVBuffer.Size.Description")
68
+#define AMF_H264_VBVBUFFER_FULLNESS                            TEXT_AMF_H264("VBVBuffer.Fullness")
69
+#define AMF_H264_VBVBUFFER_FULLNESS_DESCRIPTION                TEXT_AMF_H264("VBVBuffer.Fullness.Description")
70
+#define AMF_H264_FILLERDATA                                    TEXT_AMF_H264("FillerData")
71
+#define AMF_H264_FILLERDATA_DESCRIPTION                        TEXT_AMF_H264("FillerData.Description")
72
+#define AMF_H264_FRAMESKIPPING                             TEXT_AMF_H264("FrameSkipping")
73
+#define AMF_H264_FRAMESKIPPING_DESCRIPTION                 TEXT_AMF_H264("FrameSkipping.Description")
74
+#define AMF_H264_ENFORCEHRDCOMPATIBILITY                   TEXT_AMF_H264("EnforceHRDCompatibility")
75
+#define AMF_H264_ENFORCEHRDCOMPATIBILITY_DESCRIPTION       TEXT_AMF_H264("EnforceHRDCompatibility.Description")
76
+
77
+// Picture Control Properties
78
+#define AMF_H264_KEYFRAME_INTERVAL                         TEXT_AMF_H264("KeyframeInterval")
79
+#define AMF_H264_KEYFRAME_INTERVAL_DESCRIPTION             TEXT_AMF_H264("KeyframeInterval.Description")
80
+#define AMF_H264_IDR_PERIOD                                    TEXT_AMF_H264("IDRPeriod")
81
+#define AMF_H264_IDR_PERIOD_DESCRIPTION                        TEXT_AMF_H264("IDRPeriod.Description")
82
+#define AMF_H264_BFRAME_PATTERN                                TEXT_AMF_H264("BFrame.Pattern")
83
+#define AMF_H264_BFRAME_PATTERN_DESCRIPTION                    TEXT_AMF_H264("BFrame.Pattern.Description")
84
+#define AMF_H264_BFRAME_DELTAQP                                TEXT_AMF_H264("BFrame.DeltaQP")
85
+#define AMF_H264_BFRAME_DELTAQP_DESCRIPTION                    TEXT_AMF_H264("BFrame.DeltaQP.Description")
86
+#define AMF_H264_BFRAME_REFERENCE                          TEXT_AMF_H264("BFrame.Reference")
87
+#define AMF_H264_BFRAME_REFERENCE_DESCRIPTION              TEXT_AMF_H264("BFrame.Reference.Description")
88
+#define AMF_H264_BFRAME_REFERENCEDELTAQP                   TEXT_AMF_H264("BFrame.ReferenceDeltaQP")
89
+#define AMF_H264_BFRAME_REFERENCEDELTAQP_DESCRIPTION       TEXT_AMF_H264("BFrame.ReferenceDeltaQP.Description")
90
+#define AMF_H264_DEBLOCKINGFILTER                          TEXT_AMF_H264("DeblockingFilter")
91
+#define AMF_H264_DEBLOCKINGFILTER_DESCRIPTION              TEXT_AMF_H264("DeblockingFilter.Description")
92
+
93
+// Miscellaneous Properties
94
+#define AMF_H264_SCANTYPE                                  TEXT_AMF_H264("ScanType")
95
+#define AMF_H264_SCANTYPE_DESCRIPTION                      TEXT_AMF_H264("ScanType.Description")
96
+#define AMF_H264_SCANTYPE_PROGRESSIVE                      TEXT_AMF_H264("ScanType.Progressive")
97
+#define AMF_H264_SCANTYPE_INTERLACED                       TEXT_AMF_H264("ScanType.Interlaced")
98
+#define AMF_H264_MOTIONESTIMATION                          TEXT_AMF_H264("MotionEstimation")
99
+#define AMF_H264_MOTIONESTIMATION_DESCRIPTION              TEXT_AMF_H264("MotionEstimation.Description")
100
+#define AMF_H264_MOTIONESTIMATION_NONE                     TEXT_AMF_H264("MotionEstimation.None")
101
+#define AMF_H264_MOTIONESTIMATION_HALF                     TEXT_AMF_H264("MotionEstimation.Half")
102
+#define AMF_H264_MOTIONESTIMATION_QUARTER                  TEXT_AMF_H264("MotionEstimation.Quarter")
103
+#define AMF_H264_MOTIONESTIMATION_BOTH                     TEXT_AMF_H264("MotionEstimation.Both")
104
+
105
+// Experimental Properties
106
+#define AMF_H264_CODINGTYPE                                    TEXT_AMF_H264("CodingType")
107
+#define AMF_H264_CODINGTYPE_DESCRIPTION                        TEXT_AMF_H264("CodingType.Description")
108
+#define AMF_H264_MAXIMUMLTRFRAMES                          TEXT_AMF_H264("MaximumLTRFrames")
109
+#define AMF_H264_MAXIMUMLTRFRAMES_DESCRIPTION              TEXT_AMF_H264("MaximumLTRFrames.Description")
110
+#define AMF_H264_MAXIMUMACCESSUNITSIZE                     TEXT_AMF_H264("MaximumAccessUnitSize")
111
+#define AMF_H264_MAXIMUMACCESSUNITSIZE_DESCRIPTION         TEXT_AMF_H264("MaximumAccessUnitSize.Description")
112
+#define AMF_H264_HEADER_INSERTION_SPACING                  TEXT_AMF_H264("HeaderInsertionSpacing")
113
+#define AMF_H264_HEADER_INSERTION_SPACING_DESCRIPTION      TEXT_AMF_H264("HeaderInsertionSpacing.Description")
114
+#define AMF_H264_WAITFORTASK                               TEXT_AMF_H264("WaitForTask")
115
+#define AMF_H264_WAITFORTASK_DESCRIPTION                   TEXT_AMF_H264("WaitForTask.Description")
116
+#define AMF_H264_PREANALYSISPASS                           TEXT_AMF_H264("PreanalysisPass")
117
+#define AMF_H264_PREANALYSISPASS_DESCRIPTION               TEXT_AMF_H264("PreanalysisPass.Description")
118
+#define AMF_H264_VBAQ                                      TEXT_AMF_H264("VBAQ")
119
+#define AMF_H264_VBAQ_DESCRIPTION                          TEXT_AMF_H264("VBAQ.Description")
120
+#define AMF_H264_GOPSIZE                                   TEXT_AMF_H264("GOPSize")
121
+#define AMF_H264_GOPSIZE_DESCRIPTION                       TEXT_AMF_H264("GOPSize.Description")
122
+#define AMF_H264_GOPALIGNMENT                              TEXT_AMF_H264("GOPAlignment")
123
+#define AMF_H264_GOPALIGNMENT_DESCRIPTION                  TEXT_AMF_H264("GOPAlignment.Description")
124
+#define AMF_H264_MAXIMUMREFERENCEFRAMES                        TEXT_AMF_H264("MaximumReferenceFrames")
125
+#define AMF_H264_MAXIMUMREFERENCEFRAMES_DESCRIPTION            TEXT_AMF_H264("MaximumReferenceFrames.Description")
126
+#define AMF_H264_SLICESPERFRAME                                TEXT_AMF_H264("SlicesPerFrame")
127
+#define AMF_H264_SLICESPERFRAME_DESCRIPTION                    TEXT_AMF_H264("SlicesPerFrame.Description")
128
+#define AMF_H264_SLICEMODE                                 TEXT_AMF_H264("SliceMode")
129
+#define AMF_H264_SLICEMODE_DESCRIPTION                     TEXT_AMF_H264("SliceMode.Description")
130
+#define AMF_H264_MAXIMUMSLICESIZE                          TEXT_AMF_H264("MaximumSliceSize")
131
+#define AMF_H264_MAXIMUMSLICESIZE_DESCRIPTION              TEXT_AMF_H264("MaximumSliceSize.Description")
132
+#define AMF_H264_SLICECONTROLMODE                          TEXT_AMF_H264("SliceControlMode")
133
+#define AMF_H264_SLICECONTROLMODE_DESCRIPTION              TEXT_AMF_H264("SliceControlMode.Description")
134
+#define AMF_H264_SLICECONTROLSIZE                          TEXT_AMF_H264("SliceControlSize")
135
+#define AMF_H264_SLICECONTROLSIZE_DESCRIPTION              TEXT_AMF_H264("SliceControlSize.Description")
136
+#define AMF_H264_INTRAREFRESH_NUMBEROFSTRIPES              TEXT_AMF_H264("IntraRefresh.NumberOfStripes")
137
+#define AMF_H264_INTRAREFRESH_NUMBEROFSTRIPES_DESCRIPTION  TEXT_AMF_H264("IntraRefresh.NumberOfStripes.Description")
138
+#define AMF_H264_INTRAREFRESH_MACROBLOCKSPERSLOT           TEXT_AMF_H264("IntraRefresh.MacroblocksPerSlot")
139
+#define AMF_H264_INTRAREFRESH_MACROBLOCKSPERSLOT_DESCRIPTION   TEXT_AMF_H264("IntraRefresh.MacroblocksPerSlot.Description")
140
+
141
+// System Properties
142
+#define AMF_H264_VIDEOAPI                                  TEXT_AMF_H264("VideoAPI")
143
+#define AMF_H264_VIDEOAPI_DESCRIPTION                      TEXT_AMF_H264("VideoAPI.Description")
144
+#define AMF_H264_VIDEOADAPTER                              TEXT_AMF_H264("VideoAdapter")
145
+#define AMF_H264_VIDEOADAPTER_DESCRIPTION                  TEXT_AMF_H264("VideoAdapter.Description")
146
+#define AMF_H264_OPENCL                                        TEXT_AMF_H264("OpenCL")
147
+#define AMF_H264_OPENCL_DESCRIPTION                            TEXT_AMF_H264("OpenCL.Description")
148
+#define AMF_H264_VIEW                                      TEXT_AMF_H264("View")
149
+#define AMF_H264_VIEW_DESCRIPTION                          TEXT_AMF_H264("View.Description")
150
+#define AMF_H264_VIEW_BASIC                                    TEXT_AMF_H264("View.Basic")
151
+#define AMF_H264_VIEW_ADVANCED                             TEXT_AMF_H264("View.Advanced")
152
+#define AMF_H264_VIEW_EXPERT                               TEXT_AMF_H264("View.Expert")
153
+#define AMF_H264_VIEW_MASTER                               TEXT_AMF_H264("View.Master")
154
+#define AMF_H264_DEBUG                                     TEXT_AMF_H264("Debug")
155
+#define AMF_H264_DEBUG_DESCRIPTION                         TEXT_AMF_H264("Debug.Description")
156
 
157
 //////////////////////////////////////////////////////////////////////////
158
 // Code
159
@@ -40,7 +187,6 @@
160
            public:
161
            static void encoder_register();
162
            static const char* get_name(void* type_data);
163
-           static const char* get_name_simple(void* type_data);
164
            static void get_defaults(obs_data_t *settings);
165
            static obs_properties_t* get_properties(void* data);
166
            
167
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Include/plugin.h -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/plugin.h Changed
187
 
1
@@ -46,8 +46,7 @@
2
 
3
 #define vstr(s) dstr(s)
4
 #define dstr(s) #s
5
-
6
-#define clamp(a,b,c) (a > c ? c : (a < b ? b : a))
7
+#define clamp(val,low,high) (val > high ? high : (val < low ? low : val))
8
 
9
 #include "Version.h"
10
 #define PLUGIN_VERSION_FULL                (((uint64_t)PLUGIN_VERSION_MAJOR << 48ull) | ((uint64_t)PLUGIN_VERSION_MINOR << 32ull) | ((uint64_t)PLUGIN_VERSION_PATCH) | ((uint64_t)PLUGIN_VERSION_BUILD))
11
@@ -60,11 +59,6 @@
12
 #define AMF_LOG_CONFIG(format, ...)        AMF_LOG(350,         format, ##__VA_ARGS__)
13
 #define AMF_LOG_DEBUG(format, ...)     AMF_LOG(LOG_DEBUG,   format, ##__VA_ARGS__)
14
 
15
-#define TEXT_T(x)                      obs_module_text_multi(x)
16
-#define TEXT_AMF(x)                        ("AMF." ## x)
17
-#define TEXT_AMF_H264(x)               (TEXT_AMF("H264." ## x))
18
-#define TEXT_AMF_UTIL(x)               (TEXT_AMF("Util." ## x))
19
-
20
 #define ThrowExceptionWithAMFError(format, res, ...) {\
21
    std::vector<char> _throwexceptionwithamferror_buf(8192);\
22
    sprintf_s(_throwexceptionwithamferror_buf.data(), _throwexceptionwithamferror_buf.size(), format, ##__VA_ARGS__, Plugin::AMD::AMF::GetInstance()->GetTrace()->GetResultText(res), res);\
23
@@ -73,142 +67,28 @@
24
 }
25
 
26
 #ifndef __FUNCTION_NAME__
27
-   #if defined(_WIN32) || defined(_WIN64)   //WINDOWS
28
-       #define __FUNCTION_NAME__   __FUNCTION__  
29
-   #else          //*NIX
30
-       #define __FUNCTION_NAME__   __func__ 
31
-   #endif
32
+#if defined(_WIN32) || defined(_WIN64)   //WINDOWS
33
+#define __FUNCTION_NAME__   __FUNCTION__  
34
+#else          //*NIX
35
+#define __FUNCTION_NAME__   __func__ 
36
+#endif
37
 #endif
38
 
39
 //////////////////////////////////////////////////////////////////////////
40
 // Defines - Translation Strings
41
 //////////////////////////////////////////////////////////////////////////
42
 
43
-// Presets
44
-#define AMF_H264_PRESET                            TEXT_AMF_H264("Preset")
45
-#define AMF_H264_PRESET_RESETTODEFAULTS            TEXT_AMF_H264("Preset.ResetToDefaults")
46
-#define AMF_H264_PRESET_RECORDING              TEXT_AMF_H264("Preset.Recording")
47
-#define AMF_H264_PRESET_HIGHQUALITY                TEXT_AMF_H264("Preset.HighQuality")
48
-#define AMF_H264_PRESET_INDISTINGUISHABLE      TEXT_AMF_H264("Preset.Indistinguishable")
49
-#define AMF_H264_PRESET_LOSSLESS               TEXT_AMF_H264("Preset.Lossless")
50
-#define AMF_H264_PRESET_TWITCH                 TEXT_AMF_H264("Preset.Twitch")
51
-#define AMF_H264_PRESET_YOUTUBE                    TEXT_AMF_H264("Preset.YouTube")
52
-
53
-// Static Properties
54
-#define AMF_H264_USAGE                         TEXT_AMF_H264("Usage")
55
-#define AMF_H264_USAGE_DESCRIPTION             TEXT_AMF_H264("Usage.Description")
56
-#define AMF_H264_USAGE_TRANSCODING             TEXT_AMF_H264("Usage.Transcoding")
57
-#define AMF_H264_USAGE_ULTRALOWLATENCY         TEXT_AMF_H264("Usage.UltraLowLatency")
58
-#define AMF_H264_USAGE_LOWLATENCY              TEXT_AMF_H264("Usage.LowLatency")
59
-#define AMF_H264_USAGE_WEBCAM                  TEXT_AMF_H264("Usage.Webcam")
60
-#define AMF_H264_QUALITY_PRESET                    TEXT_AMF_H264("QualityPreset")
61
-#define AMF_H264_QUALITY_PRESET_DESCRIPTION        TEXT_AMF_H264("QualityPreset.Description")
62
-#define AMF_H264_QUALITY_PRESET_SPEED          TEXT_AMF_H264("QualityPreset.Speed")
63
-#define AMF_H264_QUALITY_PRESET_BALANCED       TEXT_AMF_H264("QualityPreset.Balanced")
64
-#define AMF_H264_QUALITY_PRESET_QUALITY            TEXT_AMF_H264("QualityPreset.Quality")
65
-#define AMF_H264_PROFILE                       TEXT_AMF_H264("Profile")
66
-#define AMF_H264_PROFILE_DESCRIPTION           TEXT_AMF_H264("Profile.Description")
67
-#define AMF_H264_PROFILELEVEL                  TEXT_AMF_H264("ProfileLevel")
68
-#define AMF_H264_PROFILELEVEL_DESCRIPTION      TEXT_AMF_H264("ProfileLevel.Description")
69
-#define AMF_H264_MAXIMUMLTRFRAMES              TEXT_AMF_H264("MaximumLTRFrames")
70
-#define AMF_H264_MAXIMUMLTRFRAMES_DESCRIPTION  TEXT_AMF_H264("MaximumLTRFrames.Description")
71
-#define AMF_H264_CODINGTYPE                        TEXT_AMF_H264("CodingType")
72
-#define AMF_H264_CODINGTYPE_DESCRIPTION            TEXT_AMF_H264("CodingType.Description")
73
-
74
-// Rate Control Properties
75
-#define AMF_H264_RATECONTROLMETHOD             TEXT_AMF_H264("RateControlMethod")
76
-#define AMF_H264_RATECONTROLMETHOD_DESCRIPTION TEXT_AMF_H264("RateControlMethod.Description")
77
-#define AMF_H264_RATECONTROLMETHOD_CQP         TEXT_AMF_H264("RateControlMethod.CQP")
78
-#define AMF_H264_RATECONTROLMETHOD_CBR         TEXT_AMF_H264("RateControlMethod.CBR")
79
-#define AMF_H264_RATECONTROLMETHOD_VBR         TEXT_AMF_H264("RateControlMethod.VBR.Peak")
80
-#define AMF_H264_RATECONTROLMETHOD_VBR_LAT     TEXT_AMF_H264("RateControlMethod.VBR.Latency")
81
-#define AMF_H264_BITRATE_TARGET                    TEXT_AMF_H264("Bitrate.Target")
82
-#define AMF_H264_BITRATE_TARGET_DESCRIPTION        TEXT_AMF_H264("Bitrate.Target.Description")
83
-#define AMF_H264_BITRATE_PEAK                  TEXT_AMF_H264("Bitrate.Peak")
84
-#define AMF_H264_BITRATE_PEAK_DESCRIPTION      TEXT_AMF_H264("Bitrate.Peak.Description")
85
-#define AMF_H264_QP_MINIMUM                        TEXT_AMF_H264("QP.Minimum")
86
-#define AMF_H264_QP_MINIMUM_DESCRIPTION            TEXT_AMF_H264("QP.Minimum.Description")
87
-#define AMF_H264_QP_MAXIMUM                        TEXT_AMF_H264("QP.Maximum")
88
-#define AMF_H264_QP_MAXIMUM_DESCRIPTION            TEXT_AMF_H264("QP.Maximum.Description")
89
-#define AMF_H264_QP_IFRAME                     TEXT_AMF_H264("QP.IFrame")
90
-#define AMF_H264_QP_IFRAME_DESCRIPTION         TEXT_AMF_H264("QP.IFrame.Description")
91
-#define AMF_H264_QP_PFRAME                     TEXT_AMF_H264("QP.PFrame")
92
-#define AMF_H264_QP_PFRAME_DESCRIPTION         TEXT_AMF_H264("QP.PFrame.Description")
93
-#define AMF_H264_QP_BFRAME                     TEXT_AMF_H264("QP.BFrame")
94
-#define AMF_H264_QP_BFRAME_DESCRIPTION         TEXT_AMF_H264("QP.BFrame.Description")
95
-#define AMF_H264_QP_BPICTURE_DELTA             TEXT_AMF_H264("QP.BPictureDelta")
96
-#define AMF_H264_QP_BPICTURE_DELTA_DESCRIPTION TEXT_AMF_H264("QP.BPictureDelta.Description")
97
-#define AMF_H264_QP_REFERENCE_BPICTURE_DELTA   TEXT_AMF_H264("QP.ReferenceBPictureDelta")
98
-#define AMF_H264_QP_REFERENCE_BPICTURE_DELTA_DESCRIPTION   TEXT_AMF_H264("QP.ReferenceBPictureDelta.Description")
99
-#define AMF_H264_VBVBUFFER                     TEXT_AMF_H264("VBVBuffer")
100
-#define AMF_H264_VBVBUFFER_DESCRIPTION         TEXT_AMF_H264("VBVBuffer.Description")
101
-#define AMF_H264_VBVBUFFER_STRICTNESS          TEXT_AMF_H264("VBVBuffer.Strictness")
102
-#define AMF_H264_VBVBUFFER_STRICTNESS_DESCRIPTION  TEXT_AMF_H264("VBVBuffer.Strictness.Description")
103
-#define AMF_H264_VBVBUFFER_SIZE                    TEXT_AMF_H264("VBVBuffer.Size")
104
-#define AMF_H264_VBVBUFFER_SIZE_DESCRIPTION        TEXT_AMF_H264("VBVBuffer.Size.Description")
105
-#define AMF_H264_VBVBUFFER_FULLNESS                TEXT_AMF_H264("VBVBuffer.Fullness")
106
-#define AMF_H264_VBVBUFFER_FULLNESS_DESCRIPTION    TEXT_AMF_H264("VBVBuffer.Fullness.Description")
107
-#define AMF_H264_FILLERDATA                        TEXT_AMF_H264("FillerData")
108
-#define AMF_H264_FILLERDATA_DESCRIPTION            TEXT_AMF_H264("FillerData.Description")
109
-#define AMF_H264_FRAMESKIPPING                 TEXT_AMF_H264("FrameSkipping")
110
-#define AMF_H264_FRAMESKIPPING_DESCRIPTION     TEXT_AMF_H264("FrameSkipping.Description")
111
-#define AMF_H264_ENFORCEHRDCOMPATIBILITY       TEXT_AMF_H264("EnforceHRDCompatibility")
112
-#define AMF_H264_ENFORCEHRDCOMPATIBILITY_DESCRIPTION   TEXT_AMF_H264("EnforceHRDCompatibility.Description")
113
-#define AMF_H264_MAXIMUMACCESSUNITSIZE         TEXT_AMF_H264("MaximumAccessUnitSize")
114
-#define AMF_H264_MAXIMUMACCESSUNITSIZE_DESCRIPTION TEXT_AMF_H264("MaximumAccessUnitSize.Description")
115
-
116
-// Picture Control Properties
117
-#define AMF_H264_KEYFRAME_INTERVAL             TEXT_AMF_H264("KeyframeInterval")
118
-#define AMF_H264_KEYFRAME_INTERVAL_DESCRIPTION TEXT_AMF_H264("KeyframeInterval.Description")
119
-#define AMF_H264_IDR_PERIOD                        TEXT_AMF_H264("IDRPeriod")
120
-#define AMF_H264_IDR_PERIOD_DESCRIPTION            TEXT_AMF_H264("IDRPeriod.Description")
121
-#define AMF_H264_HEADER_INSERTION_SPACING      TEXT_AMF_H264("HeaderInsertionSpacing")
122
-#define AMF_H264_HEADER_INSERTION_SPACING_DESCRIPTION  TEXT_AMF_H264("HeaderInsertionSpacing.Description")
123
-#define AMF_H264_BPICTURE_PATTERN              TEXT_AMF_H264("BPicture.Pattern")
124
-#define AMF_H264_BPICTURE_PATTERN_DESCRIPTION  TEXT_AMF_H264("BPicture.Pattern.Description")
125
-#define AMF_H264_BPICTURE_REFERENCE                TEXT_AMF_H264("BPicture.Reference")
126
-#define AMF_H264_BPICTURE_REFERENCE_DESCRIPTION    TEXT_AMF_H264("BPicture.Reference.Description")
127
-#define AMF_H264_DEBLOCKINGFILTER              TEXT_AMF_H264("DeblockingFilter")
128
-#define AMF_H264_DEBLOCKINGFILTER_DESCRIPTION  TEXT_AMF_H264("DeblockingFilter.Description")
129
-#define AMF_H264_SLICESPERFRAME                    TEXT_AMF_H264("SlicesPerFrame")
130
-#define AMF_H264_SLICESPERFRAME_DESCRIPTION        TEXT_AMF_H264("SlicesPerFrame.Description")
131
-#define AMF_H264_INTRAREFRESHNUMMBSPERSLOT     TEXT_AMF_H264("IntraRefreshNumMBsPerSlot")
132
-#define AMF_H264_INTRAREFRESHNUMMBSPERSLOT_DESCRIPTION TEXT_AMF_H264("IntraRefreshNumMBsPerSlot.Description")
133
-
134
-// Miscellaneous Properties
135
-#define AMF_H264_SCANTYPE                      TEXT_AMF_H264("ScanType")
136
-#define AMF_H264_SCANTYPE_DESCRIPTION          TEXT_AMF_H264("ScanType.Description")
137
-#define AMF_H264_SCANTYPE_PROGRESSIVE          TEXT_AMF_H264("ScanType.Progressive")
138
-#define AMF_H264_SCANTYPE_INTERLACED           TEXT_AMF_H264("ScanType.Interlaced")
139
-#define AMF_H264_MOTIONESTIMATION              TEXT_AMF_H264("MotionEstimation")
140
-#define AMF_H264_MOTIONESTIMATION_DESCRIPTION  TEXT_AMF_H264("MotionEstimation.Description")
141
-#define AMF_H264_MOTIONESTIMATION_NONE         TEXT_AMF_H264("MotionEstimation.None")
142
-#define AMF_H264_MOTIONESTIMATION_HALF         TEXT_AMF_H264("MotionEstimation.Half")
143
-#define AMF_H264_MOTIONESTIMATION_QUARTER      TEXT_AMF_H264("MotionEstimation.Quarter")
144
-#define AMF_H264_MOTIONESTIMATION_BOTH         TEXT_AMF_H264("MotionEstimation.Both")
145
-
146
-// System Properties
147
-#define AMF_H264_DEVICE                            TEXT_AMF_H264("Device")
148
-#define AMF_H264_DEVICE_DESCRIPTION                TEXT_AMF_H264("Device.Description")
149
-#define AMF_H264_USE_OPENCL                        TEXT_AMF_H264("UseOpenCL")
150
-#define AMF_H264_USE_OPENCL_DESCRIPTION            TEXT_AMF_H264("UseOpenCL.Description")
151
-#define AMF_H264_VIEW                          TEXT_AMF_H264("View")
152
-#define AMF_H264_VIEW_DESCRIPTION              TEXT_AMF_H264("View.Description")
153
-#define AMF_H264_VIEW_BASIC                        TEXT_AMF_H264("View.Basic")
154
-#define AMF_H264_VIEW_ADVANCED                 TEXT_AMF_H264("View.Advanced")
155
-#define AMF_H264_VIEW_EXPERT                   TEXT_AMF_H264("View.Expert")
156
-#define AMF_H264_VIEW_MASTER                   TEXT_AMF_H264("View.Master")
157
-#define AMF_H264_UNLOCK_PROPERTIES             TEXT_AMF_H264("UnlockProperties")
158
-#define AMF_H264_UNLOCK_PROPERTIES_DESCRIPTION TEXT_AMF_H264("UnlockProperties.Description")
159
-#define AMF_H264_DEBUG                         TEXT_AMF_H264("Debug")
160
-#define AMF_H264_DEBUG_DESCRIPTION             TEXT_AMF_H264("Debug.Description")
161
+#define TEXT_T(x)                      obs_module_text_multi(x)
162
+#define TEXT_AMF(x)                        ("AMF." ## x)
163
+#define TEXT_AMF_H264(x)               (TEXT_AMF("H264." ## x))
164
+#define TEXT_AMF_UTIL(x)               (TEXT_AMF("Util." ## x))
165
 
166
 // Utility
167
-#define AMF_UTIL_DEFAULT                       TEXT_AMF_UTIL("Default")
168
-#define AMF_UTIL_AUTOMATIC                     TEXT_AMF_UTIL("Automatic")
169
-#define AMF_UTIL_MANUAL                            TEXT_AMF_UTIL("Manual")
170
-#define AMF_UTIL_TOGGLE_DISABLED               TEXT_AMF_UTIL("Toggle.Disabled")
171
-#define AMF_UTIL_TOGGLE_ENABLED                    TEXT_AMF_UTIL("Toggle.Enabled")
172
+#define AMF_UTIL_DEFAULT                                   TEXT_AMF_UTIL("Default")
173
+#define AMF_UTIL_AUTOMATIC                                 TEXT_AMF_UTIL("Automatic")
174
+#define AMF_UTIL_MANUAL                                        TEXT_AMF_UTIL("Manual")
175
+#define AMF_UTIL_TOGGLE_DISABLED                           TEXT_AMF_UTIL("Toggle.Disabled")
176
+#define AMF_UTIL_TOGGLE_ENABLED                                TEXT_AMF_UTIL("Toggle.Enabled")
177
 
178
 //////////////////////////////////////////////////////////////////////////
179
 // Threading Specific
180
@@ -223,4 +103,4 @@
181
 void SetThreadName(std::thread* thread, const char* threadName);
182
 void SetThreadName(const char* threadName);
183
 
184
-#endif
185
\ No newline at end of file
186
+#endif
187
obs-studio-0.16.6.tar.xz/plugins/enc-amf/README.md -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/README.md Changed
93
 
1
@@ -6,7 +6,90 @@
2
 
3
 Read [CONTRIBUTING.md](https://github.com/Xaymar/obs-studio_amf-encoder-plugin/blob/master/CONTRIBUTING.md) for a guide on how to start.
4
 
5
-## MIT License
6
+# Contributors
7
+These people have helped (in one way or another) making this project possible. Without them, this project would have most likely not been where it is.
8
+
9
+| Who | What |
10
+| --- | ---- |
11
+| [Jim](https://github.com/jp9000) | Origin of the Open Broadcaster Software, provided support for development questions. |
12
+| [jackun](http://github.com/jackun) | The awesome person that started it all with his own Classic and Studio fork.<br>Thanks to him this project even exists today. |
13
+| [Xaymar](http://github.com/Xaymar) | Just the guy who spent a week staring at his monitors, trying to figure out how to make it work. |
14
+| GolDAce | CrowdIn integration. |
15
+| [leporel](https://github.com/leporel) | Provided ru-RU language files (Russian) |
16
+| [max20091](https://github.com/max20091) | Provided vi-VN language files (Vietnamese) |
17
+| [M4RK22](https://github.com/M4RK22) | Provided es-ES language files (Spanish) |
18
+| [niteforce](https://github.com/niteforce) | Provided hu-HU language files (Hungarian) |
19
+| [nwgat](https://github.com/nwgat) | Provided nb-NO language files (Norwegian) |
20
+| [wazerstar](https://github.com/wazerstar) | Provided da-DK language files (Danish) |
21
+| AMD | Providing Media SDK and later providing the AMF SDK. Also for incredibly fast fixing of bugs. |
22
+
23
+## The Amazing Supporters
24
+Special thanks go out to those that have either donated to the project directly or have decided to put some of their spare money into [my Patreon](https://patreon.com/xaymar). You guys rock!
25
+
26
+**[Jim](https://github.com/jp9000)**  
27
+Basically created the entire OBS project, without him it wouldn't even be here.
28
+
29
+**Kytos/M4RK22** <!-- https://www.patreon.com/user?u=3762404 -->
30
+Im happy to support a nice recording plugin for AMD users.  
31
+Patron: 2016 August-November  
32
+[Website](https://markitos.ovh), [Steam](http://steamcommunity.com/id/markitos22/)  
33
+
34
+**nwgat.ninja** <!-- https://www.patreon.com/user?u=2885495 -->  
35
+nwgat.ninja is proud to support Xaymars Technology Projects.  
36
+Patron: 2016 August-November  
37
+[Website](https://nwgat.ninja)
38
+
39
+**Mattheus Wiegand**  
40
+Patron: 2016 August, September  
41
+[Twitter](https://twitter.com/Morphy2k/), [GitHub](https://github.com/Morphy2k)  
42
+
43
+**Jeremy "razorlikes" Nieth** <!-- https://www.patreon.com/user?u=2463662 -->  
44
+I like to support this project because it gives me a way to stream without having to sacrifice immense amounts of cpu resources for encoding.  
45
+Patron: 2016 August-November  
46
+[Twitch](https://twitch.tv/razorlikes), [GitHub](https://github.com/razorlikes)
47
+
48
+**Kristian Kirkesæther** <!-- https://www.patreon.com/user?u=3963961 -->  
49
+Patron: 2016 September-November
50
+
51
+**vektorDex** <!-- https://www.patreon.com/vDex -->  
52
+Patron: 2016 September-November  
53
+[Website](http://blog-of-dex.de/), [Twitter](https://twitter.com/vektordex), [Studio](http://digitaldawnstudios.com)
54
+
55
+**AJ** <!-- https://www.patreon.com/user?u=3931856 -->  
56
+Patron: 2016 September-November
57
+
58
+**SneakyJoe** <!-- https://www.patreon.com/sneaky4oe -->  
59
+Russian streamer and stream teacher, AMD fanboy. Wants to make AMD great again.  
60
+Patron: 2016 September-November  
61
+[Website](http://sneakyjoe.ru/), [YouTube](https://www.youtube.com/channel/UCUmRv5GwQcsnxXRzuPCGr-Q)
62
+
63
+**Nicholas Kreimeyer** <!-- https://www.patreon.com/user?u=280867 -->  
64
+Patron: 2016 October, November
65
+
66
+**noext** <!-- https://www.patreon.com/user?u=3209509 -->  
67
+Patron: 2016 October
68
+
69
+**John Difool** <!-- https://www.patreon.com/user?u=3972864 -->  
70
+John Difool der alte Sack  
71
+Patron: 2016 October, November  
72
+[YouTube](https://www.youtube.com/channel/UC5FPsFLQh4ah0-vz-eoZlOA)
73
+
74
+**DaOrgest**  <!-- https://www.patreon.com/daorgest -->
75
+Currently studying computer and I do YouTube for a hobby  
76
+Patron: 2016 September-November  
77
+[Website](http://daorgest.me), [YouTube](http://youtube.com/daorgest)
78
+
79
+**Nucu** <!-- https://www.patreon.com/user?u=187366 -->  
80
+Thanks AMD and Xaymar to make hardware encoding possible.  
81
+Patron: 2016 August-November
82
+
83
+**Daniel Bagge** <!-- https://www.patreon.com/user?u=2457937 -->  
84
+Patron: 2016 September-November
85
+
86
+**Cihangir Ceviren** <!-- https://www.patreon.com/user?u=4509018 -->  
87
+Patron: 2016 November
88
+
89
+# MIT License
90
 
91
 Copyright (c) 2016 Michael Fabian Dirks
92
 
93
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/bg-BG.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/bg-BG.ini Changed
10
 
1
@@ -1,5 +1,6 @@
2
+AMF.Util.Default="По подразбиране"
3
+AMF.Util.Manual="Ръчно"
4
 AMF.H264.Profile="Профил"
5
 AMF.H264.View.Advanced="Разширения"
6
 AMF.H264.Debug="Дебъг"
7
-AMF.Util.Default="По подразбиране"
8
-AMF.Util.Manual="Ръчно"
9
+
10
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/ca-ES.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/ca-ES.ini Changed
57
 
1
@@ -1,3 +1,8 @@
2
+AMF.Util.Default="Per defecte"
3
+AMF.Util.Automatic="Automàtic"
4
+AMF.Util.Manual="Manual"
5
+AMF.Util.Toggle.Disabled="Desactivat"
6
+AMF.Util.Toggle.Enabled="Activat"
7
 AMF.H264.Preset="Configuració preestablerta"
8
 AMF.H264.Preset.Recording="S'està enregistrant"
9
 AMF.H264.Preset.HighQuality="Alta qualitat"
10
@@ -16,10 +21,6 @@
11
 AMF.H264.QualityPreset.Quality="Qualitat"
12
 AMF.H264.Profile="Perfil"
13
 AMF.H264.ProfileLevel="Nivell de perfil"
14
-AMF.H264.MaximumLTRFrames="Fotogrames màxims LTR"
15
-AMF.H264.ScanType="Tipus d'exploració"
16
-AMF.H264.ScanType.Progressive="Progressiu"
17
-AMF.H264.ScanType.Interlaced="Entrellaçat"
18
 AMF.H264.RateControlMethod="Mètode de control del flux"
19
 AMF.H264.RateControlMethod.CQP="QP constant (CQP)"
20
 AMF.H264.RateControlMethod.CBR="Flux constant (CBR)"
21
@@ -32,30 +33,23 @@
22
 AMF.H264.QP.IFrame="I-Frame QP"
23
 AMF.H264.QP.PFrame="P-Frame QP"
24
 AMF.H264.QP.BFrame="B-Frame QP"
25
-AMF.H264.QP.BPictureDelta="B-Picture Delta QP"
26
-AMF.H264.QP.ReferenceBPictureDelta="QP Delta en B-Pictures de referencia"
27
 AMF.H264.FillerData="Dades a omplir"
28
 AMF.H264.FrameSkipping="Omissió de fotogrames"
29
 AMF.H264.EnforceHRDCompatibility="Força la compatibilitat amb HRD"
30
-AMF.H264.BPicture.Pattern="Patró B-Picture"
31
-AMF.H264.BPicture.Reference="Referència B-Picture"
32
 AMF.H264.DeblockingFilter="Filtre d'eliminació de blocs"
33
+AMF.H264.ScanType="Tipus d'exploració"
34
+AMF.H264.ScanType.Progressive="Progressiu"
35
+AMF.H264.ScanType.Interlaced="Entrellaçat"
36
 AMF.H264.MotionEstimation.None="Cap"
37
 AMF.H264.MotionEstimation.Half="Meitat de píxel"
38
 AMF.H264.MotionEstimation.Quarter="Quart de Píxel"
39
-AMF.H264.Device="Dispositiu"
40
+AMF.H264.MaximumLTRFrames="Fotogrames màxims LTR"
41
 AMF.H264.View="Mode de visualització"
42
 AMF.H264.View.Description="Quines propietats han de ser visibles. No rebreu suport si feu servir el mode de vista 'Expert' o 'Màster'."
43
 AMF.H264.View.Basic="Bàsic"
44
 AMF.H264.View.Advanced="Avançat"
45
 AMF.H264.View.Expert="Expert"
46
 AMF.H264.View.Master="Màster"
47
-AMF.H264.UnlockProperties="Desbloqueja les propietats"
48
-AMF.H264.UnlockProperties.Description="Desbloqueja algunes propietats a la seva màxima capacitat en lloc de limitar-les de forma parcial."
49
 AMF.H264.Debug="Depuració"
50
 AMF.H264.Debug.Description="Habilita el registre d'informació de depuració addicional, ha de ser activat quan necessiteu ajuda amb aquest codificador."
51
-AMF.Util.Default="Per defecte"
52
-AMF.Util.Automatic="Automàtic"
53
-AMF.Util.Manual="Manual"
54
-AMF.Util.Toggle.Disabled="Desactivat"
55
-AMF.Util.Toggle.Enabled="Activat"
56
+
57
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/cs-CZ.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/cs-CZ.ini Changed
74
 
1
@@ -1,3 +1,8 @@
2
+AMF.Util.Default="Výchozí"
3
+AMF.Util.Automatic="Automatické"
4
+AMF.Util.Manual="Manuální"
5
+AMF.Util.Toggle.Disabled="Zakázáno"
6
+AMF.Util.Toggle.Enabled="Povoleno"
7
 AMF.H264.Preset="Profil"
8
 AMF.H264.Preset.ResetToDefaults="Obnovit výchozí"
9
 AMF.H264.Preset.Recording="Nahrávání"
10
@@ -16,11 +21,6 @@
11
 AMF.H264.QualityPreset.Quality="Kvalita"
12
 AMF.H264.Profile="Profil"
13
 AMF.H264.ProfileLevel="Úroveň profilu"
14
-AMF.H264.MaximumLTRFrames="Maximální počet LTR snímků"
15
-AMF.H264.ScanType="Typ skenování"
16
-AMF.H264.ScanType.Description="Určuje použitou metodu skenování, vždy ponechejte na 'Progresivní'."
17
-AMF.H264.ScanType.Progressive="Progresivní"
18
-AMF.H264.ScanType.Interlaced="Prokládané"
19
 AMF.H264.RateControlMethod="Metoda řízení"
20
 AMF.H264.RateControlMethod.CQP="Konstantní QP (CQP)"
21
 AMF.H264.RateControlMethod.CBR="Konstantní bitrate (CBR)"
22
@@ -32,32 +32,41 @@
23
 AMF.H264.Bitrate.Peak.Description="Bitrate, kterého se máme snažit nepřekročit v celé sekvenci."
24
 AMF.H264.QP.Minimum="Minimální QP"
25
 AMF.H264.QP.Maximum="Maximální QP"
26
+AMF.H264.QP.IFrame="I-Frame QP"
27
+AMF.H264.QP.IFrame.Description="Pevná hodnota QP používaná pro I-Frames."
28
+AMF.H264.QP.PFrame="P-Frame QP"
29
+AMF.H264.QP.PFrame.Description="Pevná hodnota QP používaná pro P-Frames."
30
+AMF.H264.QP.BFrame="B-Frame QP"
31
+AMF.H264.QP.BFrame.Description="Pevná hodnota QP používaná pro B-Frames."
32
+AMF.H264.VBVBuffer="VBV Buffer"
33
 AMF.H264.FillerData="Filtrovat data"
34
 AMF.H264.FrameSkipping="Přeskakování snímků"
35
 AMF.H264.EnforceHRDCompatibility="Vynutit kompatibilitu s HRD"
36
 AMF.H264.KeyframeInterval="Interval klíčový snímků"
37
 AMF.H264.KeyframeInterval.Description="Kolik vteřin by mělo být mezi ne-zahazovatelnými snímky.\nTaké ovládá velikost sekvence(GOP)."
38
+AMF.H264.ScanType="Typ skenování"
39
+AMF.H264.ScanType.Description="Určuje použitou metodu skenování, vždy ponechejte na 'Progresivní'."
40
+AMF.H264.ScanType.Progressive="Progresivní"
41
+AMF.H264.ScanType.Interlaced="Prokládané"
42
 AMF.H264.MotionEstimation="Odhad pohybu"
43
 AMF.H264.MotionEstimation.Description="Odhad pohybu umožňuje enkodéru snížit požadovaný bitrate předpovídáním, kam se určitý pixel posunul."
44
 AMF.H264.MotionEstimation.None="Žádný"
45
 AMF.H264.MotionEstimation.Half="Polovina pixelu"
46
 AMF.H264.MotionEstimation.Quarter="Čtvrtina pixelu"
47
 AMF.H264.MotionEstimation.Both="Polovina & čtvrtina pixelu"
48
-AMF.H264.Device="Zařízení"
49
-AMF.H264.UseOpenCL="Použít OpenCL"
50
-AMF.H264.UseOpenCL.Description="Měl by enkodér použít OpenCL pro potvrzování samostatných snímků?"
51
+AMF.H264.MaximumLTRFrames="Maximální počet LTR snímků"
52
+AMF.H264.VideoAPI="Grafické rozhraní (API)"
53
+AMF.H264.VideoAPI.Description="Které rozhraní má být použito pro kódování."
54
+AMF.H264.VideoAdapter="Grafický adaptér"
55
+AMF.H264.VideoAdapter.Description="Adaptér, který má být použit pro kódování."
56
+AMF.H264.OpenCL="OpenCL"
57
+AMF.H264.OpenCL.Description="Má být použit OpenCL pro vkládání jednotlivých snímků?"
58
 AMF.H264.View="Režim zobrazení"
59
 AMF.H264.View.Description="Které možnosti mají být zobrazeny. Nezískáte žádnou pomoc při použití módu 'Expert' či 'Master'."
60
 AMF.H264.View.Basic="Základní"
61
 AMF.H264.View.Advanced="Pokročilý"
62
 AMF.H264.View.Expert="Expert"
63
 AMF.H264.View.Master="Master"
64
-AMF.H264.UnlockProperties="Odblokovat vlastnosti"
65
-AMF.H264.UnlockProperties.Description="Odblokuje určité vlastnosti do jejich plného rozsahu místo omezování do určitého."
66
 AMF.H264.Debug="Ladění"
67
 AMF.H264.Debug.Description="Zapne rozšířené protokolování, mělo by být zapnuto, pokud pořebujete pomoci s tmto enkodérem."
68
-AMF.Util.Default="Výchozí"
69
-AMF.Util.Automatic="Automatické"
70
-AMF.Util.Manual="Manuální"
71
-AMF.Util.Toggle.Disabled="Zakázáno"
72
-AMF.Util.Toggle.Enabled="Povoleno"
73
+
74
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/da-DK.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/da-DK.ini Changed
36
 
1
@@ -1,3 +1,6 @@
2
+AMF.Util.Default="Standard"
3
+AMF.Util.Toggle.Disabled="Deaktiveret"
4
+AMF.Util.Toggle.Enabled="Aktiveret"
5
 AMF.H264.Usage.Transcoding="Transcoding"
6
 AMF.H264.Usage.UltraLowLatency="Ekstrem Lav Ventetid"
7
 AMF.H264.Usage.LowLatency="Lav Ventetid"
8
@@ -7,9 +10,6 @@
9
 AMF.H264.QualityPreset.Quality="Kvalitet (Bedste Kvalitet)"
10
 AMF.H264.Profile="Profil"
11
 AMF.H264.ProfileLevel="Profil Niveau"
12
-AMF.H264.ScanType="Scan Type"
13
-AMF.H264.ScanType.Progressive="Progressive"
14
-AMF.H264.ScanType.Interlaced="Interlaced"
15
 AMF.H264.RateControlMethod="Rate Control Method"
16
 AMF.H264.RateControlMethod.CQP="Constant QP (CQP)"
17
 AMF.H264.RateControlMethod.CBR="Constant Bitrate (CBR)"
18
@@ -22,13 +22,11 @@
19
 AMF.H264.QP.IFrame="I-Frame QP"
20
 AMF.H264.QP.PFrame="P-Frame QP"
21
 AMF.H264.QP.BFrame="B-Frame QP"
22
-AMF.H264.QP.BPictureDelta="B-Picture Delta QP"
23
 AMF.H264.FillerData="Filler Data"
24
 AMF.H264.FrameSkipping="Billede skip"
25
 AMF.H264.EnforceHRDCompatibility="Tving HRD Kompatibilitet"
26
-AMF.H264.BPicture.Pattern="B-Picture Pattern"
27
-AMF.H264.BPicture.Reference="B-Picture Reference"
28
 AMF.H264.DeblockingFilter="Deblocking Filter"
29
-AMF.Util.Default="Standard"
30
-AMF.Util.Toggle.Disabled="Deaktiveret"
31
-AMF.Util.Toggle.Enabled="Aktiveret"
32
+AMF.H264.ScanType="Scan Type"
33
+AMF.H264.ScanType.Progressive="Progressive"
34
+AMF.H264.ScanType.Interlaced="Interlaced"
35
+
36
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/de-DE.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/de-DE.ini Changed
159
 
1
@@ -1,3 +1,8 @@
2
+AMF.Util.Default="Standard"
3
+AMF.Util.Automatic="Automatisch"
4
+AMF.Util.Manual="Manuell"
5
+AMF.Util.Toggle.Disabled="Deaktiviert"
6
+AMF.Util.Toggle.Enabled="Aktiviert"
7
 AMF.H264.Preset="Voreinstellungen"
8
 AMF.H264.Preset.ResetToDefaults="Standardeinstellungen wiederherstellen"
9
 AMF.H264.Preset.Recording="Aufnahme"
10
@@ -17,17 +22,9 @@
11
 AMF.H264.QualityPreset.Balanced="Ausgeglichen"
12
 AMF.H264.QualityPreset.Quality="Qualität"
13
 AMF.H264.Profile="Profil"
14
-AMF.H264.Profile.Description="Welches H.264 Profil soll für das codieren verwendet werden:\n- 'Baseline' hat die größte Betriebssystemunterstützung,\n- 'Main' wird von älteren Geräten unterstützt (empfohlen sofern das Ziel mobile Geräte sind),\n- 'High' wird von neueren Geräten unterstützt (empfohlen)."
15
+AMF.H264.Profile.Description="Welches H.264 Profil soll für die Kodierung verwendet werden, sortiert von höchster Qualität bis am weitesten verbeiteten Unterstützung."
16
 AMF.H264.ProfileLevel="Profillevel"
17
 AMF.H264.ProfileLevel.Description="Welches H.264 Profil Level für das verarbeiten verwendet werden soll:\n- '\@AMF.Util.Automatic\@' errechnet das beste Profil Level für die gegebene Frame Rate und Frame Größe,\n- '4.1' unterstützt 1920x1080 30FPS, 1280x720 60FPS, 960x540 90FPS\n- '4.2' unterstützt 1920x1080 60FPS, 1280x720 120FPS, 960x540 172FPS\n- '5.0' unterstützt 1920x1080 60FPS, 1280x720 144FPS, 960x540 172FPS\n- '5.1' unterstützt 3840x2160 30FPS, 1920x1080 120FPS, 1280x720 172FPS, 960x540 172FPS\n- '5.2' unterstützt 3840x2160 60FPS, 1920x1080 172FPS, 1280x720 172FPS, 960x540 172FPS"
18
-AMF.H264.MaximumLTRFrames="Maximale Langzeitreferenz-Bilder"
19
-AMF.H264.MaximumLTRFrames.Description="Langzeitreferenz (LTR) Bilder ist ein Feature das dem Codierer erlaubt, einige Bilder innerhalb einer Sequenz als referenzierbar zu markieren.\nDies kann einen positiven Effekt auf die Qualität haben sofern B-Bilder nicht unterstützt oder gewollt sind.\nLTR Bilder können nicht zusammen mit B-Bildern verwendet werden und der Codierer wird B-Bilder deaktivieren sofern diese verwendet werden."
20
-AMF.H264.CodingType="Codierungstyp"
21
-AMF.H264.CodingType.Description="Welcher Codierungstyp verwendet werden soll:\n* \@AMF.Util.Default\@ lässt AMF entscheiden (empfohlen).\n* CALVC (Context-Adaptive Variable-Length Coding) ist schneller aber größer.\n* CABAC (Context-Adaptive Binary Arithmetic Coding) ist langsamer aber kleiner."
22
-AMF.H264.ScanType="Abtastverfahren"
23
-AMF.H264.ScanType.Description="Welches Abtastverfahren verwendet werden soll. Sollte immer '\@AMF.H264.ScanType.Progressive\@' sein."
24
-AMF.H264.ScanType.Progressive="Progressiv"
25
-AMF.H264.ScanType.Interlaced="Zeilensprung"
26
 AMF.H264.RateControlMethod="Ratenkontrollmethode"
27
 AMF.H264.RateControlMethod.Description="Welche Ratenkontrollmethode verwendet werden soll:\n- '\@AMF.H264.RateControlMethod.CQP\@' setzt feste QP (Quantifizierungsparameter) Werte für I-/P-/B- Bilder,\n- '\@AMF.H264.RateControlMethod.CBR\@' bleibt auf der Zielbitrate (mithilfe von Füllungsdaten) (empfohlen für das Streamen),\n- '\@AMF.H264.RateControlMethod.VBR\@' bleibt unter der Spitzenbitrate,\n- '\@AMF.H264.RateControlMethod.VBR_LAT\@' bleibt nahe der Zielbitrate sofern GPU-Latenz und GPU-Benutzung dies erlauben, ansonsten wird eine höhere Bitrate verwendet (empfohlen für Aufnahmen)."
28
 AMF.H264.RateControlMethod.CQP="Konstante QP (CQP)"
29
@@ -43,22 +40,18 @@
30
 AMF.H264.QP.Maximum="Maximale QP"
31
 AMF.H264.QP.Maximum.Description="Höchster QP (Quantifizierungsparameter) wert der in einem Bild verwendet wird."
32
 AMF.H264.QP.IFrame="I-Einzelbild QP"
33
-AMF.H264.QP.IFrame.Description="Fester QP (Quantifizierungsparameter) wert der für I-Bilder genutzt wird.\nI-Bild QP sollte höher oder gleich wie der von P- und B-Bildern sein."
34
+AMF.H264.QP.IFrame.Description="Fester QP wert der für I-Bilder verwendet wird."
35
 AMF.H264.QP.PFrame="P-Einzelbild QP"
36
-AMF.H264.QP.PFrame.Description="Fester QP (Quantifizierungsparameter) wert der für P-Bilder genutzt wird.\nI-Bild QP sollte höher oder gleich wie der von B-Bildern sein."
37
+AMF.H264.QP.PFrame.Description="Fester QP wert der für P-Bilder verwendet wird."
38
 AMF.H264.QP.BFrame="B-Einzelbild QP"
39
-AMF.H264.QP.BFrame.Description="Fester QP (Quantifizierungsparameter) wert der für B-Bilder genutzt wird."
40
-AMF.H264.QP.BPictureDelta="B-Bild Delta QP"
41
-AMF.H264.QP.BPictureDelta.Description="Delta QP wert zum letzten nicht-Referenz B-Bild."
42
-AMF.H264.QP.ReferenceBPictureDelta="Referenz B-Bild Delta QP"
43
-AMF.H264.QP.ReferenceBPictureDelta.Description="Delta QP wert zum letzten Referenz B-Bild."
44
+AMF.H264.QP.BFrame.Description="Fester QP wert der für B-Bilder verwendet wird."
45
 AMF.H264.VBVBuffer="VBV Buffer"
46
 AMF.H264.VBVBuffer.Description="Welche Methode genutzt werden soll um die VBV-Puffergröße zu bestimmen:\n- '\@AMF.Util.Automatic\@' errechnet diese mithilfe einer Strengeneinschränkung,\n- '\@AMF.Util.Manual\@' erlaubt es dem Nutzer die Größe zu kontrollieren.\n
47
 VBV (Videopufferungsverifizierer) Puffer wird von verschiedenen Ratenkontrollmethoden genutzt um die gesamte Bitrate innerhalb der Begrenzungen zu halten."
48
 AMF.H264.VBVBuffer.Strictness="VBV Buffer Genauigkeit"
49
-AMF.H264.VBVBuffer.Strictness.Description="Wie streng der VBV Buffer sein soll, wobei 100% fast exakt die Zielbitrate und 0% komplett unbeschränkt ist."
50
+AMF.H264.VBVBuffer.Strictness.Description="Legt die Einschränkungsstärke des VBV Buffers fest, wobei 100% so eingeschränkt wie möglich ist und 0% komplett uneingeschränkt."
51
 AMF.H264.VBVBuffer.Size="VBV Buffer Größe"
52
-AMF.H264.VBVBuffer.Size.Description="Die Größe des VBV Buffers der für die Bitratenkontrollen in einer Sequenz verwendet wird.\nEine kleine Größe ergibt eine fast perfekte Übereinstimmung mit der Bitrate aber hat einen größeren Performanzeinfluss."
53
+AMF.H264.VBVBuffer.Size.Description="Die Größe des VBV Buffers, welcher für die Bitratenkontrolle in einer Sequenz verwendet wird."
54
 AMF.H264.VBVBuffer.Fullness="VBV Buffer Füllung"
55
 AMF.H264.VBVBuffer.Fullness.Description="Wie voll der VBV Buffer anfangs ist, hat nur einen Effekt auf die erste Sequenz beim codieren."
56
 AMF.H264.FillerData="Füllungsdaten"
57
@@ -66,47 +59,77 @@
58
 AMF.H264.FrameSkipping="Bildüberspringung"
59
 AMF.H264.FrameSkipping.Description="Bildüberspringung erlaubt es dem Codierer, Bilder zu überspringen um die Zielbitrate einzuhalten.\nWenn der Codierer ein Bild überspringt, fügt dieser stattdessen ein repeat-last-frame NAL in den Stream ein.\nKann bei sehr niedrigen Zielbitraten helfen."
60
 AMF.H264.EnforceHRDCompatibility="Erzwinge HRD Kompatiblität"
61
-AMF.H264.EnforceHRDCompatibility.Description="Erzwinge Hypothetischer-Referenz-Decodierer Limitierungen welches die maximale Änderung des QP werts innerhalb eines Bildes begrenzt.\nNicht empfohlen für Aufname oder Streamen und sollte nur verwendet werden sofern das Ziel sehr alte Geräte mit einem Softwarereferenz Decodierer sind."
62
-AMF.H264.MaximumAccessUnitSize="Maximale Zugriffseinheitsgröße"
63
-AMF.H264.MaximumAccessUnitSize.Description="Größte Größe einer Zugriffseinheit für einen NAL. Ein Wert von 0 erlaubt es dem Codierer die beste Größte zu wählen."
64
+AMF.H264.EnforceHRDCompatibility.Description="Erzwinge Hypothetischer-Referenz-Decodierer Limitierungen welches die maximale Änderung des QP werts innerhalb eines Bildes begrenzt."
65
 AMF.H264.KeyframeInterval="Keyframeintervall"
66
 AMF.H264.KeyframeInterval.Description="Definiert die Distanz zwischen Keyframes in Sekunden. Setzt auch die Größe einer GOP-Sequenz fest."
67
 AMF.H264.IDRPeriod="IDR Zeitraum"
68
 AMF.H264.IDRPeriod.Description="Definiert die Distanz zwischen Sofortigen-Decodierer-Aktualisierungen (IDR) in Frames. Setzt auch die Größe einer GOP-Sequenz fest."
69
-AMF.H264.HeaderInsertionSpacing="Dateikopfeinfügungsabstand"
70
-AMF.H264.HeaderInsertionSpacing.Description="Wie viele Bilder zwischen NAL-Kopfzeilen sein sollen. Es wird nicht empfohlen dies von 0 (automatisch) zu ändern."
71
-AMF.H264.BPicture.Pattern="B-Bild Muster"
72
-AMF.H264.BPicture.Pattern.Description="Wie viele B-Bilder sollen erlaubt sein für das codieren. Dies hat einen positiven Einfluss auf Qualität und einen negativen Einfluss auf Performanz.\nWird nur von der 2. und 3. Generation an VCE-Karten unterstützt."
73
-AMF.H264.BPicture.Reference="B-Bild Referenz"
74
-AMF.H264.BPicture.Reference.Description="Erlaube B-Bilder andere B-Bilder zu verwenden.\nSehr großer Einfluss auf Performanz, wenig Einfluss auf Qualität."
75
+AMF.H264.BFrame.Pattern="B-Bilder"
76
+AMF.H264.BFrame.Pattern.Description="Wie viele B-Bilder beim codieren verwendet werden sollen.\nWird von der 2ten und 3ten generation an VCE-Karten unterstützt. Negativer Einfluss auf Codierungsperformanz."
77
+AMF.H264.BFrame.DeltaQP="Delta QP für B-Bilder"
78
+AMF.H264.BFrame.DeltaQP.Description="Delta QP wert zum letzten I- or P-Bild für nicht referenzierbare B-Bilder."
79
+AMF.H264.BFrame.Reference="Referenzierbare B-Bilder"
80
+AMF.H264.BFrame.Reference.Description="Erlaube einem B-Bild andere B-Bilder als referenz zu verwenden, anstatt nur P- und I-Bilder."
81
+AMF.H264.BFrame.ReferenceDeltaQP="Delta QP für referenzierbare B-Bilder"
82
+AMF.H264.BFrame.ReferenceDeltaQP.Description="Delta QP wert zum letzten I- or P-Bild für referenzierbare B-Bilder."
83
 AMF.H264.DeblockingFilter="Entblockungsfilter"
84
 AMF.H264.DeblockingFilter.Description="Setze die Markierung dass der Decodierer einen Entblockungsfilter verwenden darf."
85
-AMF.H264.SlicesPerFrame="Slices pro Frame"
86
-AMF.H264.SlicesPerFrame.Description="Wie viele I-Bild-Schnitte sollen mit jedem Bild gespeichert werden?\nEin Wert von Null erlaubt es dem Codierer während dem codieren die Entscheidung zu treffen.\nIntra-Erneuerungs-Codieren wird genutzt für schnelleres abspielen und suchen."
87
-AMF.H264.IntraRefreshNumMBsPerSlot="Intra-Refresh Anzahl der Makroblöcke pro Slot"
88
-AMF.H264.IntraRefreshNumMBsPerSlot.Description="Wie viele Makroblöcke sollen pro Slot gespeichert werden?\nEin Wert von Null erlaubt es dem Codierer während dem codieren die Entscheidung zu treffen.\nIntra-Erneuerungs-Codieren wird genutzt für schnelleres abspielen und suchen."
89
+AMF.H264.ScanType="Abtastverfahren"
90
+AMF.H264.ScanType.Description="Welches Abtastverfahren verwendet werden soll. Sollte immer '\@AMF.H264.ScanType.Progressive\@' sein."
91
+AMF.H264.ScanType.Progressive="Progressiv"
92
+AMF.H264.ScanType.Interlaced="Zeilensprung"
93
 AMF.H264.MotionEstimation="Bewegungsschätzung"
94
 AMF.H264.MotionEstimation.Description="Bewegungsschätzung erlaubt des dem Codierer die benötigte Bitrate zu reduzieren durch das herausfinden, wo ein Pixel hinbewegt wurde."
95
 AMF.H264.MotionEstimation.None="Keine"
96
 AMF.H264.MotionEstimation.Half="Halb-Pixel"
97
 AMF.H264.MotionEstimation.Quarter="Viertel-Pixel"
98
 AMF.H264.MotionEstimation.Both="Halb- & Viertel-Pixel"
99
-AMF.H264.Device="Gerät"
100
-AMF.H264.Device.Description="Welches Gerät für das codieren verwendet werden soll.\nBenötigt einen anderen Speichertyp als 'Host'."
101
-AMF.H264.UseOpenCL="Benutze OpenCL"
102
-AMF.H264.UseOpenCL.Description="Soll OpenCL verwendet werden, um Einzelbilder zum Codierer zu senden?"
103
+AMF.H264.CodingType="Codierungstyp"
104
+AMF.H264.CodingType.Description="Welcher Codierungstyp verwendet werden soll:\n* \@AMF.Util.Default\@ lässt AMF entscheiden (empfohlen).\n* CALVC (Context-Adaptive Variable-Length Coding) ist schneller aber größer.\n* CABAC (Context-Adaptive Binary Arithmetic Coding) ist langsamer aber kleiner."
105
+AMF.H264.MaximumLTRFrames="Maximale Langzeitreferenz-Bilder"
106
+AMF.H264.MaximumLTRFrames.Description="Langzeitreferenz (LTR) Bilder ist ein Feature das dem Codierer erlaubt, einige Bilder innerhalb einer Sequenz als referenzierbar zu markieren.\nLTR Bilder können nicht zusammen mit B-Bildern verwendet werden und der Codierer wird B-Bilder deaktivieren sofern diese verwendet werden."
107
+AMF.H264.MaximumAccessUnitSize="Maximale Zugriffseinheitsgröße"
108
+AMF.H264.MaximumAccessUnitSize.Description="Größte Größe einer Zugriffseinheit für einen NAL."
109
+AMF.H264.HeaderInsertionSpacing="Dateikopfeinfügungsabstand"
110
+AMF.H264.HeaderInsertionSpacing.Description="Wie viele Bilder zwischen NAL-Kopfzeilen sein sollen."
111
+AMF.H264.WaitForTask="Warte auf Arbeit"
112
+AMF.H264.WaitForTask.Description="Unbekannt, Experimentell"
113
+AMF.H264.PreAnalysisPass="Voranalyse Durchlauf"
114
+AMF.H264.PreAnalysisPass.Description="Unbekannt, Experimentell"
115
+AMF.H264.VBAQ="VBAQ"
116
+AMF.H264.VBAQ.Description="Unbekannt, Experimentell"
117
+AMF.H264.GOPSize="GOP Größe"
118
+AMF.H264.GOPSize.Description="Unbekannt, Experimentell"
119
+AMF.H264.GOPAlignment="GOP Angleichung"
120
+AMF.H264.GOPAlignment.Description="Unbekannt, Experimentell"
121
+AMF.H264.MaximumReferenceFrames="Maximale Referenzbilder"
122
+AMF.H264.MaximumReferenceFrames.Description="Unbekannt, Experimentell"
123
+AMF.H264.SlicesPerFrame="Slices pro Frame"
124
+AMF.H264.SlicesPerFrame.Description="Wie viele I-Bild-Schnitte sollen mit jedem Bild gespeichert werden?\nEin Wert von Null erlaubt es dem Codierer während dem codieren die Entscheidung zu treffen.\nIntra-Erneuerungs-Codieren wird genutzt für schnelleres abspielen und suchen."
125
+AMF.H264.SliceMode="Schnittmodus"
126
+AMF.H264.SliceMode.Description="Unbekannt, Experimentell"
127
+AMF.H264.MaximumSliceSize="Maximale Schnittgröße"
128
+AMF.H264.MaximumSliceSize.Description="Unbekannt, Experimentell"
129
+AMF.H264.SliceControlMode="Schnittkontrollmodus"
130
+AMF.H264.SliceControlMode.Description="Unbekannt, Experimentell"
131
+AMF.H264.SliceControlSize="Schnittkontrollgröße"
132
+AMF.H264.SliceControlSize.Description="Unbekannt, Experimentell"
133
+AMF.H264.IntraRefresh.NumberOfStripes="Intra-Refresh Anzahl an Streifen"
134
+AMF.H264.IntraRefresh.NumberOfStripes.Description="Unbekannt, Experimentell"
135
+AMF.H264.IntraRefresh.MacroblocksPerSlot="Intra-Refresh Makroblöcke pro Slot"
136
+AMF.H264.IntraRefresh.MacroblocksPerSlot.Description="Wie viele Makroblöcke sollen pro Slot gespeichert werden?\nEin Wert von Null schaltet diese Feature ab.\nIntra-Erneuerungs-Codieren wird genutzt für schnelleres abspielen und suchen."
137
+AMF.H264.VideoAPI="Video API"
138
+AMF.H264.VideoAPI.Description="Welche API für das codieren verwendet werden soll."
139
+AMF.H264.VideoAdapter="Video Adapter"
140
+AMF.H264.VideoAdapter.Description="Welcher Adapter für das codieren verwendet werden soll."
141
+AMF.H264.OpenCL="OpenCL"
142
+AMF.H264.OpenCL.Description="Soll der Codierer OpenCL zum übertragen der Bilder verwenden?"
143
 AMF.H264.View="Ansichtsmodus"
144
 AMF.H264.View.Description="Welche Eigenschaften sollen sichtbar sein?\nDas benutzen von '\@AMF.H264.View.Master\@' disqualifiziert dich von jeglichen Support."
145
 AMF.H264.View.Basic="Grundlegend"
146
 AMF.H264.View.Advanced="Erweitert"
147
 AMF.H264.View.Expert="Experte"
148
 AMF.H264.View.Master="Meister"
149
-AMF.H264.UnlockProperties="Entsperre Einstellungen"
150
-AMF.H264.UnlockProperties.Description="Entsperre einige Einstellungen, sodass diese die volle Reichweite haben, anstatt nur eine begrenzte."
151
 AMF.H264.Debug="Debug"
152
 AMF.H264.Debug.Description="Aktiviere erweiterte Debug-Nachrichten, sollte aktiv sein wenn man Hilfe erwartet mit diesem Codierer."
153
-AMF.Util.Default="Standard"
154
-AMF.Util.Automatic="Automatisch"
155
-AMF.Util.Manual="Manuell"
156
-AMF.Util.Toggle.Disabled="Deaktiviert"
157
-AMF.Util.Toggle.Enabled="Aktiviert"
158
+
159
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/el-GR.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/el-GR.ini Changed
4
 
1
@@ -1,1 +1,2 @@
2
 AMF.H264.Profile="Προφίλ"
3
+
4
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/en-US.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/en-US.ini Changed
190
 
1
@@ -1,4 +1,11 @@
2
-# Presets
3
+# Shared
4
+AMF.Util.Default="Default"
5
+AMF.Util.Automatic="Automatic"
6
+AMF.Util.Manual="Manual"
7
+AMF.Util.Toggle.Disabled="Disabled"
8
+AMF.Util.Toggle.Enabled="Enabled"
9
+# H264
10
+# - Preset
11
 AMF.H264.Preset="Preset"
12
 AMF.H264.Preset.ResetToDefaults="Reset to Defaults"
13
 AMF.H264.Preset.Recording="Recording"
14
@@ -7,7 +14,7 @@
15
 AMF.H264.Preset.Lossless="Lossless"
16
 AMF.H264.Preset.Twitch="Twitch"
17
 AMF.H264.Preset.YouTube="YouTube"
18
-# Static Properties
19
+# - Startup Properties
20
 AMF.H264.Usage="Usage"
21
 AMF.H264.Usage.Description="What usage AMF should be tuned for:\n- '\@AMF.H264.Usage.Transcoding\@' is general purpose transcoding (recommended),\n- '\@AMF.H264.Usage.UltraLowLatency\@' is for really low latency encoding,\n- '\@AMF.H264.Usage.LowLatency\@' is similar to above with a slightly higher latency.\nStreaming only supports '\@AMF.H264.Usage.Transcoding\@', all other values can be used for recording."
22
 AMF.H264.Usage.Transcoding="Transcoding"
23
@@ -19,20 +26,12 @@
24
 AMF.H264.QualityPreset.Balanced="Balanced"
25
 AMF.H264.QualityPreset.Quality="Quality"
26
 AMF.H264.Profile="Profile"
27
-AMF.H264.Profile.Description="Which H.264 Profile to use for encoding:\n- 'Baseline' has the biggest platform support,\n- 'Main' is supported by older devices (recommended if targeting mobile devices),\n- 'High' is supported by current devices (recommended)."
28
+AMF.H264.Profile.Description="Which H.264 Profile to use for encoding, sorted from highest quality to most widespread support."
29
 AMF.H264.ProfileLevel="Profile Level"
30
 AMF.H264.ProfileLevel.Description="Which H.264 Profile Level to use for encoding:\n- '\@AMF.Util.Automatic\@' calculates the best profile level for the given Frame Rate and Frame Size,\n- '4.1' supports 1920x1080 30FPS, 1280x720 60FPS, 960x540 90FPS\n- '4.2' supports 1920x1080 60FPS, 1280x720 120FPS, 960x540 172FPS\n- '5.0' supports 1920x1080 60FPS, 1280x720 144FPS, 960x540 172FPS\n- '5.1' supports 3840x2160 30FPS, 1920x1080 120FPS, 1280x720 172FPS, 960x540 172FPS\n- '5.2' supports 3840x2160 60FPS, 1920x1080 172FPS, 1280x720 172FPS, 960x540 172FPS"
31
-AMF.H264.MaximumLTRFrames="Maximum LTR Frames"
32
-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.\nThis can have a positive effect on quality when B-Pictures are not supported or wanted.\nLTR Frames can't be used with B-Pictures and the encoder will disable B-Pictures if these are used."
33
-AMF.H264.CodingType="Coding Type"
34
-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."
35
-AMF.H264.ScanType="Scan Type"
36
-AMF.H264.ScanType.Description="Which scanning method to use, always leave this on '\@AMF.H264.ScanType.Progressive\@'."
37
-AMF.H264.ScanType.Progressive="Progressive"
38
-AMF.H264.ScanType.Interlaced="Interlaced"
39
-# Rate Control Properties
40
+# - Rate Control Properties
41
 AMF.H264.RateControlMethod="Rate Control Method"
42
-AMF.H264.RateControlMethod.Description="What rate control method should be used:\n- '\@AMF.H264.RateControlMethod.CQP\@' assigns fixed I-/P-/B-Frame QP (Quantization Parameter) values,\n- '\@AMF.H264.RateControlMethod.CBR\@' stays at the given Target Bitrate (using Filler Data) (recommended for streaming),\n- '\@AMF.H264.RateControlMethod.VBR\@' stays below the given Peak Bitrate,\n- '\@AMF.H264.RateControlMethod.VBR_LAT\@' stays close to the Target Bitrate if GPU latency and load allow for it, otherwise will use higher bitrate (recommended for recording)."
43
+AMF.H264.RateControlMethod.Description="What rate control method should be used:\n- '\@AMF.H264.RateControlMethod.CQP\@' assigns fixed I-/P-/B-Frame QP values,\n- '\@AMF.H264.RateControlMethod.CBR\@' stays at the given Target Bitrate (using Filler Data) (recommended for streaming),\n- '\@AMF.H264.RateControlMethod.VBR\@' stays below the given Peak Bitrate,\n- '\@AMF.H264.RateControlMethod.VBR_LAT\@' stays close to the Target Bitrate if GPU latency and load allow for it, otherwise will use higher bitrate (recommended for recording)."
44
 AMF.H264.RateControlMethod.CQP="Constant QP (CQP)"
45
 AMF.H264.RateControlMethod.CBR="Constant Bitrate (CBR)"
46
 AMF.H264.RateControlMethod.VBR.Peak="Variable Bitrate (Peak Constrained) (VBR)"
47
@@ -42,25 +41,21 @@
48
 AMF.H264.Bitrate.Peak="Peak Bitrate"
49
 AMF.H264.Bitrate.Peak.Description="Bitrate to attempt to maximally peak to in the overall sequence."
50
 AMF.H264.QP.Minimum="Minimum QP"
51
-AMF.H264.QP.Minimum.Description="Lowest QP (Quantization Parameter) value to use in a frame."
52
+AMF.H264.QP.Minimum.Description="Lowest QP value to use in a Frame."
53
 AMF.H264.QP.Maximum="Maximum QP"
54
-AMF.H264.QP.Maximum.Description="Highest QP (Quantization Parameter) value to use in a frame."
55
+AMF.H264.QP.Maximum.Description="Highest QP value to use in a Frame."
56
 AMF.H264.QP.IFrame="I-Frame QP"
57
-AMF.H264.QP.IFrame.Description="Fixed QP (Quantization Parameter) value to use for I-Frames.\nI-Frame QP should be at or higher than P- and B-Frame QP."
58
+AMF.H264.QP.IFrame.Description="Fixed QP value to use for I-Frames."
59
 AMF.H264.QP.PFrame="P-Frame QP"
60
-AMF.H264.QP.PFrame.Description="Fixed QP (Quantization Parameter) value to use for P-Frames.\nP-Frame QP should be at or higher than B-Frame QP."
61
+AMF.H264.QP.PFrame.Description="Fixed QP value to use for P-Frames."
62
 AMF.H264.QP.BFrame="B-Frame QP"
63
-AMF.H264.QP.BFrame.Description="Fixed QP (Quantization Parameter) value to use for B-Frames."
64
-AMF.H264.QP.BPictureDelta="B-Picture Delta QP"
65
-AMF.H264.QP.BPictureDelta.Description="Delta QP (Quantization Parameter) value to the last non-reference B-Picture."
66
-AMF.H264.QP.ReferenceBPictureDelta="Reference B-Picture Delta QP"
67
-AMF.H264.QP.ReferenceBPictureDelta.Description="Delta QP (Quantization Parameter) value to the last reference B-Picture."
68
+AMF.H264.QP.BFrame.Description="Fixed QP value to use for B-Frames."
69
 AMF.H264.VBVBuffer="VBV Buffer"
70
 AMF.H264.VBVBuffer.Description="What method should be used to determine the VBV Buffer Size:\n- '\@AMF.Util.Automatic\@' calculates the size using a strictness constraint,\n- '\@AMF.Util.Manual\@' allows the user to control the size.\nVBV (Video Buffering Verifier) Buffer is used by certain Rate Control Methods to keep the overall bitrate within the given constraints."
71
 AMF.H264.VBVBuffer.Strictness="VBV Buffer Strictness"
72
-AMF.H264.VBVBuffer.Strictness.Description="How strict the VBV Buffer is, with 100% being almost exactly the targetted Bitrate and 0% being unrestricted."
73
+AMF.H264.VBVBuffer.Strictness.Description="Determines the strictness of the VBV Buffer, with 100% being as strict as possible and 0% being unrestricted."
74
 AMF.H264.VBVBuffer.Size="VBV Buffer Size"
75
-AMF.H264.VBVBuffer.Size.Description="The size of the VBV Buffer which is used for Bitrate control in a sequence.\nA small size results in an almost perfect bitrate match but has a larger performance impact."
76
+AMF.H264.VBVBuffer.Size.Description="The size of the VBV Buffer which is used for Bitrate control in a sequence."
77
 AMF.H264.VBVBuffer.Fullness="VBV Buffer Fullness"
78
 AMF.H264.VBVBuffer.Fullness.Description="How full the VBV Buffer initially is, will only affect the initial sequence of encoding."
79
 AMF.H264.FillerData="Filler Data"
80
@@ -68,51 +63,80 @@
81
 AMF.H264.FrameSkipping="Frame Skipping"
82
 AMF.H264.FrameSkipping.Description="Frame Skipping allows the encoder to drop frames in order to meet Target Bitrate requirements.\nWhen the encoder drops a frame it instead insert a repeat-last-frame NAL into the stream.\nCan help with very low Target Bitrates."
83
 AMF.H264.EnforceHRDCompatibility="Enforce HRD Compatibility"
84
-AMF.H264.EnforceHRDCompatibility.Description="Enforce Hypothetical Reference Decoder restrictions which limit the maximum QP value change within a frame.\nNot recommended for recording or streaming and should only be used for targeting very old devices that only have reference software decoders."
85
-AMF.H264.MaximumAccessUnitSize="Maximum Access Unit Size"
86
-AMF.H264.MaximumAccessUnitSize.Description="Largest Size of an Access Unit for a NAL. A value of 0 allows the encoder to pick the best one."
87
-# Picture Control Properties
88
+AMF.H264.EnforceHRDCompatibility.Description="Enforce Hypothetical Reference Decoder restrictions which limit the maximum QP value change within a frame."
89
+# - Picture Control Properties
90
 AMF.H264.KeyframeInterval="Keyframe Interval"
91
 AMF.H264.KeyframeInterval.Description="Defines the distance between Keyframes in seconds. Also controls GOP-sequence size."
92
 AMF.H264.IDRPeriod="IDR Period"
93
 AMF.H264.IDRPeriod.Description="Defines the distance between Instantaneous Decoding Refreshes (IDR) in frames. Also controls GOP-sequence size."
94
-AMF.H264.HeaderInsertionSpacing="Header Insertion Spacing"
95
-AMF.H264.HeaderInsertionSpacing.Description="How many frames should be between NAL headers. It is not recommended to change this from 0 (automatic)."
96
-AMF.H264.BPicture.Pattern="B-Picture Pattern"
97
-AMF.H264.BPicture.Pattern.Description="How many B-Pictures should be allowed for encoding, has a positive impact on quality and negative impact on performance.\nSupported by 2nd and 3rd Generation VCE cards."
98
-AMF.H264.BPicture.Reference="B-Picture Reference"
99
-AMF.H264.BPicture.Reference.Description="Allow B-Pictures to reference other B-Pictures additionally to P- and I-Frames.\nImproves quality slightly but lowers encoding performance."
100
+AMF.H264.BFrame.Pattern="B-Frames"
101
+AMF.H264.BFrame.Pattern.Description="The amount of B-Frames to use while encoding.\nSupported by 2nd and 3rd Generation VCE cards. Negative impact on encoding performance."
102
+AMF.H264.BFrame.DeltaQP="Delta QP for B-Frames"
103
+AMF.H264.BFrame.DeltaQP.Description="Delta QP value to the last I- or P-Frame for non-referenceable B-Frames."
104
+AMF.H264.BFrame.Reference="Referenceable B-Frames"
105
+AMF.H264.BFrame.Reference.Description="Allow a B-Frame to also use B-Frames as reference, instead of just P- and I-Frames."
106
+AMF.H264.BFrame.ReferenceDeltaQP="Delta QP for referenceable B-Frames"
107
+AMF.H264.BFrame.ReferenceDeltaQP.Description="Delta QP value to the last I- or P-Frame for referenceable B-Frames."
108
 AMF.H264.DeblockingFilter="Deblocking Filter"
109
 AMF.H264.DeblockingFilter.Description="Sets the flag that the decoder is allowed to use a Deblocking Filter for the encoded stream."
110
-AMF.H264.SlicesPerFrame="Slices Per Frame"
111
-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."
112
-AMF.H264.IntraRefreshNumMBsPerSlot="Intra-Refresh Number of Macroblocks Per Slot"
113
-AMF.H264.IntraRefreshNumMBsPerSlot.Description="How many Macroblocks should be stored in each slot?\nA value of zero lets the encoder decide on the fly.\nIntra-Refresh encoding is used for faster playback and seeking."
114
-# Miscellaneous Properties
115
+# - Miscellaneous Properties
116
+AMF.H264.ScanType="Scan Type"
117
+AMF.H264.ScanType.Description="Which scanning method to use, always leave this on '\@AMF.H264.ScanType.Progressive\@'."
118
+AMF.H264.ScanType.Progressive="Progressive"
119
+AMF.H264.ScanType.Interlaced="Interlaced"
120
 AMF.H264.MotionEstimation="Motion Estimation"
121
 AMF.H264.MotionEstimation.Description="Motion Estimation allows the encoder to reduce needed bitrate by estimating where a pixel went."
122
 AMF.H264.MotionEstimation.None="None"
123
 AMF.H264.MotionEstimation.Half="Half-Pixel"
124
 AMF.H264.MotionEstimation.Quarter="Quarter-Pixel"
125
 AMF.H264.MotionEstimation.Both="Half- & Quarter-Pixel"
126
-# System Properties
127
-AMF.H264.Device="Device"
128
-AMF.H264.Device.Description="Which Device to use for encoding.\nRequires Memory Type to not be set to 'Host'."
129
-AMF.H264.UseOpenCL="Use OpenCL"
130
-AMF.H264.UseOpenCL.Description="Should the Encoder use OpenCL to submit the individual frames?"
131
+# - Experimental Properties
132
+AMF.H264.CodingType="Coding Type"
133
+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."
134
+AMF.H264.MaximumLTRFrames="Maximum LTR Frames"
135
+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."
136
+AMF.H264.MaximumAccessUnitSize="Maximum Access Unit Size"
137
+AMF.H264.MaximumAccessUnitSize.Description="Largest Size of an Access Unit for a NAL."
138
+AMF.H264.HeaderInsertionSpacing="Header Insertion Spacing"
139
+AMF.H264.HeaderInsertionSpacing.Description="How many frames should be between NAL headers."
140
+AMF.H264.WaitForTask="Wait For Task"
141
+AMF.H264.WaitForTask.Description="Unknown, Experimental"
142
+AMF.H264.PreAnalysisPass="Pre Analysis Pass"
143
+AMF.H264.PreAnalysisPass.Description="Unknown, Experimental"
144
+AMF.H264.VBAQ="VBAQ"
145
+AMF.H264.VBAQ.Description="Unknown, Experimental"
146
+AMF.H264.GOPSize="GOP Size"
147
+AMF.H264.GOPSize.Description="Unknown, Experimental"
148
+AMF.H264.GOPAlignment="GOP Alignment"
149
+AMF.H264.GOPAlignment.Description="Unknown, Experimental"
150
+AMF.H264.MaximumReferenceFrames="Maximum Reference Frames"
151
+AMF.H264.MaximumReferenceFrames.Description="Unknown, Experimental"
152
+AMF.H264.SlicesPerFrame="Slices Per Frame"
153
+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."
154
+AMF.H264.SliceMode="Slice Mode"
155
+AMF.H264.SliceMode.Description="Unknown, Experimental"
156
+AMF.H264.MaximumSliceSize="Maximum Slice Size"
157
+AMF.H264.MaximumSliceSize.Description="Unknown, Experimental"
158
+AMF.H264.SliceControlMode="Slice Control Mode"
159
+AMF.H264.SliceControlMode.Description="Unknown, Experimental"
160
+AMF.H264.SliceControlSize="Slice Control Size"
161
+AMF.H264.SliceControlSize.Description="Unknown, Experimental"
162
+AMF.H264.IntraRefresh.NumberOfStripes="Intra-Refresh Number of Stripes"
163
+AMF.H264.IntraRefresh.NumberOfStripes.Description="Unknown, Experimental"
164
+AMF.H264.IntraRefresh.MacroblocksPerSlot="Intra-Refresh Macroblocks per Slot"
165
+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."
166
+# - System Properties
167
+AMF.H264.VideoAPI="Video API"
168
+AMF.H264.VideoAPI.Description="Which API to use for encoding."
169
+AMF.H264.VideoAdapter="Video Adapter"
170
+AMF.H264.VideoAdapter.Description="Which Adapter to use for encoding."
171
+AMF.H264.OpenCL="OpenCL"
172
+AMF.H264.OpenCL.Description="Should the Encoder use OpenCL to submit the individual frames?"
173
 AMF.H264.View="View Mode"
174
 AMF.H264.View.Description="What properties should be shown?\nUsing '\@AMF.H264.View.Master\@' will disqualify you from receiving support."
175
 AMF.H264.View.Basic="Basic"
176
 AMF.H264.View.Advanced="Advanced"
177
 AMF.H264.View.Expert="Expert"
178
 AMF.H264.View.Master="Master"
179
-AMF.H264.UnlockProperties="Unlock Properties"
180
-AMF.H264.UnlockProperties.Description="Unlock certain properties to their full range instead of limiting them to a partial range."
181
 AMF.H264.Debug="Debug"
182
 AMF.H264.Debug.Description="Enable additional debug logging, should be active whenever you need support with this encoder."
183
-# Utility
184
-AMF.Util.Default="Default"
185
-AMF.Util.Automatic="Automatic"
186
-AMF.Util.Manual="Manual"
187
-AMF.Util.Toggle.Disabled="Disabled"
188
-AMF.Util.Toggle.Enabled="Enabled"
189
\ No newline at end of file
190
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/es-ES.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/es-ES.ini Changed
149
 
1
@@ -1,3 +1,8 @@
2
+AMF.Util.Default="Por defecto"
3
+AMF.Util.Automatic="Automático"
4
+AMF.Util.Manual="Manual"
5
+AMF.Util.Toggle.Disabled="Deshabilitado"
6
+AMF.Util.Toggle.Enabled="Habilitado"
7
 AMF.H264.Preset="Preajuste"
8
 AMF.H264.Preset.ResetToDefaults="Restablecer por defecto"
9
 AMF.H264.Preset.Recording="Grabación"
10
@@ -20,12 +25,6 @@
11
 AMF.H264.Profile.Description="Que perfil H.264 a utilizar para la codificación:\n- 'Baseline' tiene el mayor soporte en las plataformas,\n- 'Main' es compatible con dispositivos algo mas anticuados (recomendado si la emisión va dirigida a dispositivos móviles),\n- 'High' es compatible con los dispositivos actuales (recomendado)."
12
 AMF.H264.ProfileLevel="Nivel del Perfil"
13
 AMF.H264.ProfileLevel.Description="Nivel de perfil H.264 a utilizar para la codificación:\n- 'Automático' calcula el mejor nivel de perfil para cierta velocidad y tamaño de fotogramas,\n- '4.1' soporta 1920x1080 30FPS, 1280x720 60FPS, 960x540 90FPS\n- '4.2' soporta 1920x1080 60FPS, 1280x720 120FPS, 960x540 172FPS\n- '5.0' soporta 1920x1080 60FPS, 1280x720 144FPS, 960x540 172FPS\n- '5.1' soporta 3840x2160 30FPS, 1920x1080 120FPS, 1280x720 172FPS, 960x540 172FPS\n- '5.2' soporta 3840x2160 60FPS, 1920x1080 172FPS, 1280x720 172FPS, 960x540 172FPS"
14
-AMF.H264.MaximumLTRFrames="Fotogramas LTR máximos"
15
-AMF.H264.MaximumLTRFrames.Description="Fotogramas de referencia a largo plazo (LTR) son una caracteristica que permite al codificador marcar ciertos frames en una secuencia como referentes.\nEsto puede tener un efecto positivo en la calidad cuando los B-Pictures no estan soportados.\nLos fotogramas LTR no pueden ser usados con B-Pictures y el codificador deshabilitará B-Pictures si se usa."
16
-AMF.H264.ScanType="Tipo de escaneo"
17
-AMF.H264.ScanType.Description="Que método de escaneo usar, dejar siempre en 'Progresivo'."
18
-AMF.H264.ScanType.Progressive="Progresivo"
19
-AMF.H264.ScanType.Interlaced="Entrelazado"
20
 AMF.H264.RateControlMethod="Método de control del flujo"
21
 AMF.H264.RateControlMethod.Description="Qué método de control de flujo debe ser usado:\n- '\@AMF.H264.RateControlMethod.CQP\@' asigna valores fijos de QP en I-/P-/B-Frames (Parámetro de cuantización),\n- '\@AMF.H264.RateControlMethod.CBR\@' se mantiene en la tasa de bits objetivo (usando Datos de relleno) (recomendado para emisiones en directo),\n- '\@AMF.H264.RateControlMethod.VBR\@' se mantiene por debajo de un pico de tasa de bits,\n- '\@AMF.H264.RateControlMethod.VBR_LAT\@' se mantiene cerca de la tasa de bits deseada si la latencia y carga de la GPU lo permite, si no se aumentará la tasa de bits (recomendado para grabaciones)."
22
 AMF.H264.RateControlMethod.CQP="QP constante (CQP)"
23
@@ -41,21 +40,17 @@
24
 AMF.H264.QP.Maximum="QP Máximo"
25
 AMF.H264.QP.Maximum.Description="Valor máximo de QP (parámetro de cuantización) a utilizar en un fotograma."
26
 AMF.H264.QP.IFrame="I-Frame QP"
27
-AMF.H264.QP.IFrame.Description="Valor de QP Fijo (parámetro de cuantización) a usar por I-Frames.\n-El valor QP de un I-Frame debe ser igual o superior al valor QP de P- y B-Frames."
28
+AMF.H264.QP.IFrame.Description="Valor fijo de QP para I-Frames."
29
 AMF.H264.QP.PFrame="P-Frame QP"
30
-AMF.H264.QP.PFrame.Description="Valor de QP Fijo (parámetro de cuantización) a usar por P-Frames.\n-El valor QP de un P-Frame debe ser igual o superior al valor QP de un B-Frame."
31
+AMF.H264.QP.PFrame.Description="Valor fijo de QP para P-Frames."
32
 AMF.H264.QP.BFrame="B-Frame QP"
33
 AMF.H264.QP.BFrame.Description="Valor de QP Fijo (parámetro de cuantización) a usar por B-Frames."
34
-AMF.H264.QP.BPictureDelta="QP Delta en B-Pictures"
35
-AMF.H264.QP.BPictureDelta.Description="QP Delta del último B-Picture que no es de referencia."
36
-AMF.H264.QP.ReferenceBPictureDelta="QP Delta en B-Pictures de referencia"
37
-AMF.H264.QP.ReferenceBPictureDelta.Description="QP Delta del último B-Picture de referencia."
38
 AMF.H264.VBVBuffer="Buffer VBV"
39
 AMF.H264.VBVBuffer.Description="Que método se debe usar para determinar el tamaño del buffer VBV:\n- 'Automático' calcula el tamaño usando una restricción estricta,\n- 'Manual' permite al usuario controlar el tamaño.\nEl buffer VBV (Verificador de Buffering de Video) es usado por ciertos métodos de control del flujo para mantener la tasa de bits dentro de los parámetros establecidos."
40
 AMF.H264.VBVBuffer.Strictness="Estricticidad del Buffer VBV"
41
-AMF.H264.VBVBuffer.Strictness.Description="Como de estricto es el buffer VBV, con 100% siendo casi exactamente la tasa de bits deseada y 0% siendo sin restricción."
42
+AMF.H264.VBVBuffer.Strictness.Description="Determina la rigidez del Buffer VBV, con 100% siendo tan estricto como sea posible y 0% sin restricción."
43
 AMF.H264.VBVBuffer.Size="Tamaño de buffer VBV"
44
-AMF.H264.VBVBuffer.Size.Description="El tamaño del Buffer VBV que es usado para el control de la tasa de bits en una secuencia.\nUn tamaño pequeño ofrece una tasa de bits con una coincidencia casi perfecta pero tiene un gran impacto en el rendimiento."
45
+AMF.H264.VBVBuffer.Size.Description="Tamaño del Buffer VBV que se utiliza para el control de Bitrate en una secuencia."
46
 AMF.H264.VBVBuffer.Fullness="Amplitud del Buffer VBV"
47
 AMF.H264.VBVBuffer.Fullness.Description="Como de lleno es el buffer VMV inicialmente, solo afectará a la secuencia inicial de la codificación."
48
 AMF.H264.FillerData="Datos de relleno"
49
@@ -64,46 +59,76 @@
50
 AMF.H264.FrameSkipping.Description="Omisión de fotogramas permite al codificador saltar fotogramas para cumplir con el requerimiento de la tasa de bits objetivo.\nCuando el codificador salta un fotograma insertará un NAL que repetirá el ultimo fotograma codificado en el stream.\nPuede ayudar con tasa de bits objetivo muy bajas."
51
 AMF.H264.EnforceHRDCompatibility="Forzar compatibilidad con HRD"
52
 AMF.H264.EnforceHRDCompatibility.Description="Forzar las restricciones del decodificador hipotético de referencia que limitan el cambio de valor máximo de QP dentro de un fotograma.\nNo recomendado para grabación o emisión en directo y solo se debe usar cuando el objetivo son dispositivos antiguos que solo tienen decodificadores de referencia por software."
53
-AMF.H264.MaximumAccessUnitSize="Tamaño máximo de la unidad de acceso"
54
-AMF.H264.MaximumAccessUnitSize.Description="Mayor tamaño de una unidad de acceso para una NAL. Un valor de 0 permite al codificador elegir el mejor."
55
 AMF.H264.KeyframeInterval="Intervalo de fotogramas clave"
56
 AMF.H264.KeyframeInterval.Description="Cuantos segundos deben haber entre fotogramas que no se pueden descartar.\nTambién controla el tamaño de la secuencia (GOP)."
57
 AMF.H264.IDRPeriod="Periodo IDR"
58
 AMF.H264.IDRPeriod.Description="Define la distancia entre Instantaneous Decoding Refreshes (IDR) en Fotogramas. También controla el tamaño de la secuencia del GOP."
59
-AMF.H264.HeaderInsertionSpacing="Espaciado de inserción de cabeceras (Frames)"
60
-AMF.H264.HeaderInsertionSpacing.Description="Cuantos fotogramas deben haber entre cabeceras NAL. No se recomienda cambiar de 0 (automatico)."
61
-AMF.H264.BPicture.Pattern="Patron de B-Pictures"
62
-AMF.H264.BPicture.Pattern.Description="Cuantas B-Pictures deben ser permitidos en la codificación, tiene un impacto positivo en la calidad y negativo en rendimiento.\nSoportado por la segunda y tercera generación de VCE."
63
-AMF.H264.BPicture.Reference="B-Pictures de referencia"
64
-AMF.H264.BPicture.Reference.Description="Permitir B-Pictures referenciar otras B-Pictures adicionalmente a P- y I-Frames.\nGran impacto en el rendimiento, poca mejora de calidad."
65
+AMF.H264.BFrame.Pattern="B-Frames"
66
+AMF.H264.BFrame.Pattern.Description="La cantidad de B-Frames a usar mientras se codifica.\nSoportado con tarjetas de 2 º y 3 º generación VCE. Impacto negativo en el rendimiento de codificación."
67
+AMF.H264.BFrame.DeltaQP="Delta QP para B-Frames"
68
+AMF.H264.BFrame.DeltaQP.Description="Valor Delta QP para el ultimo I- o P-Frame para B-Frames no referenciables."
69
+AMF.H264.BFrame.Reference="B-Frames referenciables"
70
+AMF.H264.BFrame.Reference.Description="Permitir a un B-Frame utilizar también B-Frames como referencia, en lugar de P - y I-Frames."
71
+AMF.H264.BFrame.ReferenceDeltaQP="Delta QP para los fotogramas referenciables"
72
+AMF.H264.BFrame.ReferenceDeltaQP.Description="Valor Delta QP para el ultimo I- o P-Frame para B-Frames referenciables."
73
 AMF.H264.DeblockingFilter="Filtro de eliminación de bloques"
74
 AMF.H264.DeblockingFilter.Description="Establece el indicador de que el decodificador está permitido a usar el Filtro de eliminación de bloques para el stream codificado."
75
-AMF.H264.SlicesPerFrame="Porciones por fotograma"
76
-AMF.H264.SlicesPerFrame.Description="Cuantas porciones I-Frame deben ser almacenados en cada fotograma?\nUn valor de 0 permite al codificador decidir al vuelo.\nLa codificación Intra-Refresh es usada para una reproducción y exploración mas fluida."
77
-AMF.H264.IntraRefreshNumMBsPerSlot="Numero de macrobloques intra-refresh por Slot"
78
-AMF.H264.IntraRefreshNumMBsPerSlot.Description="Cuantos macrobloques deben ser almacenados en cada slot?\nUn valor de 0 permite al codificador decidir al vuelo.\nLa codificación Intra-Refresh es usada para una reproducción y exploración mas fluida."
79
+AMF.H264.ScanType="Tipo de escaneo"
80
+AMF.H264.ScanType.Description="Que método de escaneo usar, dejar siempre en 'Progresivo'."
81
+AMF.H264.ScanType.Progressive="Progresivo"
82
+AMF.H264.ScanType.Interlaced="Entrelazado"
83
 AMF.H264.MotionEstimation="Estimación de movimiento"
84
 AMF.H264.MotionEstimation.Description="Estimación de movimiento permite al codificador reducir el flujo de datos necesario estimando de donde vienen los pixeles."
85
 AMF.H264.MotionEstimation.None="Ninguno"
86
 AMF.H264.MotionEstimation.Half="Mitad de Pixel"
87
 AMF.H264.MotionEstimation.Quarter="Cuarto de Pixel"
88
 AMF.H264.MotionEstimation.Both="Mitad y cuarto de Pixel"
89
-AMF.H264.Device="Dispositivo"
90
-AMF.H264.Device.Description="Que dispositivo usar para codificar.\nRequiere que el tipo de memoria seleccionado no sea 'Host'."
91
-AMF.H264.UseOpenCL="Usar OpenCL"
92
-AMF.H264.UseOpenCL.Description="Debe el codificador usar OpenCL para entregar los fotogramas individuales?"
93
+AMF.H264.CodingType="Tipo de codificación"
94
+AMF.H264.CodingType.Description="Qué tipo de codificación utilizar:\n* \@AMF.Util.Default\@ deja que AMF lo decida (recomendado).\n* CALVC (Context-Adaptive Variable-Length Coding) es más rápido, pero más grande.\n* CABAC (Context-Adaptive Binary Arithmetic Coding) es más lento, pero más pequeño."
95
+AMF.H264.MaximumLTRFrames="Fotogramas LTR máximos"
96
+AMF.H264.MaximumLTRFrames.Description="Fotogramas de referencia a largo plazo (LTR) son una característica que permite al codificador marcar ciertos frames en una secuencia como referentes por un largo tiempo.\nLos fotogramas LTR no pueden ser usados con B-Pictures y el codificador deshabilitará B-Pictures si se usa."
97
+AMF.H264.MaximumAccessUnitSize="Tamaño máximo de la unidad de acceso"
98
+AMF.H264.MaximumAccessUnitSize.Description="Mayor tamaño de una unidad de acceso para una NAL. Un valor de 0 permite al codificador elegir el mejor."
99
+AMF.H264.HeaderInsertionSpacing="Espaciado de inserción de cabeceras (Frames)"
100
+AMF.H264.HeaderInsertionSpacing.Description="Cuantos fotogramas deben haber entre cabeceras NAL. No se recomienda cambiar de 0 (automatico)."
101
+AMF.H264.WaitForTask="Esperar para la tarea"
102
+AMF.H264.WaitForTask.Description="Desconocido, Experimental"
103
+AMF.H264.PreAnalysisPass="Pase de pre-análisis"
104
+AMF.H264.PreAnalysisPass.Description="Desconocido, Experimental"
105
+AMF.H264.VBAQ="VBAQ"
106
+AMF.H264.VBAQ.Description="Desconocido, Experimental"
107
+AMF.H264.GOPSize="Tamaño del GOP"
108
+AMF.H264.GOPSize.Description="Desconocido, Experimental"
109
+AMF.H264.GOPAlignment="Alineación del GOP"
110
+AMF.H264.GOPAlignment.Description="Desconocido, Experimental"
111
+AMF.H264.MaximumReferenceFrames="Fotogramas de referencia máximos"
112
+AMF.H264.MaximumReferenceFrames.Description="Desconocido, Experimental"
113
+AMF.H264.SlicesPerFrame="Porciones por fotograma"
114
+AMF.H264.SlicesPerFrame.Description="Cuantas porciones I-Frame deben ser almacenados en cada fotograma?\nUn valor de 0 permite al codificador decidir al vuelo.\nLa codificación Intra-Refresh es usada para una reproducción y exploración mas fluida."
115
+AMF.H264.SliceMode="Modo de porciones"
116
+AMF.H264.SliceMode.Description="Desconocido, Experimental"
117
+AMF.H264.MaximumSliceSize="Tamaño máximo de la porción"
118
+AMF.H264.MaximumSliceSize.Description="Desconocido, Experimental"
119
+AMF.H264.SliceControlMode="Modo de control de la porción"
120
+AMF.H264.SliceControlMode.Description="Desconocido, Experimental"
121
+AMF.H264.SliceControlSize="Control de tamaño de la porción"
122
+AMF.H264.SliceControlSize.Description="Desconocido, Experimental"
123
+AMF.H264.IntraRefresh.NumberOfStripes="Numero de lineas Intra-Refresh"
124
+AMF.H264.IntraRefresh.NumberOfStripes.Description="Desconocido, Experimental"
125
+AMF.H264.IntraRefresh.MacroblocksPerSlot="Numero de macrobloques intra-refresh por Slot"
126
+AMF.H264.IntraRefresh.MacroblocksPerSlot.Description="Cuantos macrobloques deben ser almacenados en cada slot?\nUn valor de 0 deshabilita esta función.\nLa codificación Intra-Refresh es usada para una reproducción y exploración mas fluida."
127
+AMF.H264.VideoAPI="API de vídeo"
128
+AMF.H264.VideoAPI.Description="Que API usar para la codificación."
129
+AMF.H264.VideoAdapter="Adaptador de video"
130
+AMF.H264.VideoAdapter.Description="Que adaptador usar para la codificación."
131
+AMF.H264.OpenCL="OpenCL"
132
+AMF.H264.OpenCL.Description="¿Debe el Codificador usar OpenCL para presentar los fotogramas individuales?"
133
 AMF.H264.View="Modo de Vista"
134
 AMF.H264.View.Description="Que propiedades deben ser visibles. No recibirás soporte si usas el modo de vista 'Experto' o 'Maestro'."
135
 AMF.H264.View.Basic="Básico"
136
 AMF.H264.View.Advanced="Avanzado"
137
 AMF.H264.View.Expert="Experto"
138
 AMF.H264.View.Master="Maestro"
139
-AMF.H264.UnlockProperties="Desbloquear propiedades"
140
-AMF.H264.UnlockProperties.Description="Desbloquea ciertas propiedades a su maxima capacidad en lugar de limitarlas de forma parcial."
141
 AMF.H264.Debug="Depurar"
142
 AMF.H264.Debug.Description="Habilita el registro de información de depuración adicional, debe ser activado cuando necesites ayuda con este codificador."
143
-AMF.Util.Default="Por defecto"
144
-AMF.Util.Automatic="Automático"
145
-AMF.Util.Manual="Manual"
146
-AMF.Util.Toggle.Disabled="Deshabilitado"
147
-AMF.Util.Toggle.Enabled="Habilitado"
148
+
149
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/eu-ES.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/eu-ES.ini Changed
88
 
1
@@ -1,3 +1,8 @@
2
+AMF.Util.Default="Lehenetsia"
3
+AMF.Util.Automatic="Automatikoa"
4
+AMF.Util.Manual="Eskuz"
5
+AMF.Util.Toggle.Disabled="Ezgaituta"
6
+AMF.Util.Toggle.Enabled="Gaituta"
7
 AMF.H264.Preset="Aurrezarrita"
8
 AMF.H264.Preset.ResetToDefaults="Berrezarri balio lehenetsiak"
9
 AMF.H264.Preset.Recording="Grabatzen"
10
@@ -18,11 +23,6 @@
11
 AMF.H264.Profile="Profila"
12
 AMF.H264.ProfileLevel="Profilaren maila"
13
 AMF.H264.ProfileLevel.Description="H.264 profilaren zein maila erabili behar da kodetzeko:\n- 'Automatic' automatikoki kalkulatzen du emandako abiadura eta fotogramen tamainarako egokiena,\n- '4.1'-ek onartzen du 1920x1080 30FPS, 1280x720 60FPS, 960x540 90FPS\n- '4.2'-k onartzen du 1920x1080 60FPS, 1280x720 120FPS\n- '5.0'-k onartzen du 1920x1080 60FPS, 1280x720 144FPS, 960x540 172FPS\n- '5.1'-k onartzen du 3840x2160 30FPS, 1920x1080 120FPS, 1280x720 172FPS, 960x540 172FPS\n- '5.2'-k onartzen du 3840x2160 60FPS, 1920x1080 172FPS, 1280x720 172FPS, 960x540 172FPS"
14
-AMF.H264.MaximumLTRFrames="Gehienezko LTR fotogramak"
15
-AMF.H264.MaximumLTRFrames.Description="Long Term Reference (LTR) Fotogramak aukera ematen dio kodegailuari sekuentzia baten hainbat fotograma erreferente moduan markatzeko.\nHonek kalitatean eragin positiboa izan dezake B-Pictures onartzen ez direnean.\nLTR Fotogramak ezin dira B-Pictures-ekin erabili eta kodegailuak B-Pictures-ak desgaituko ditu hauek erabiltzean."
16
-AMF.H264.ScanType="Eskaneatze mota"
17
-AMF.H264.ScanType.Progressive="Progresiboa"
18
-AMF.H264.ScanType.Interlaced="Gurutzelarkatua"
19
 AMF.H264.RateControlMethod="Emaria kontrolatzeko metodoa"
20
 AMF.H264.RateControlMethod.CQP="Konstantea QP (CQP)"
21
 AMF.H264.RateControlMethod.CBR="Bit emari konstantea (CBR)"
22
@@ -35,8 +35,6 @@
23
 AMF.H264.QP.IFrame="I-Frame QP"
24
 AMF.H264.QP.PFrame="P-Frame QP"
25
 AMF.H264.QP.BFrame="B-Frame QP"
26
-AMF.H264.QP.BPictureDelta="B-Picture Delta QP"
27
-AMF.H264.QP.ReferenceBPictureDelta="B-Picture Delta QP erreferentzia"
28
 AMF.H264.VBVBuffer="VBV bufferra"
29
 AMF.H264.VBVBuffer.Strictness="VBV bufferraren zorroztasuna"
30
 AMF.H264.VBVBuffer.Size="VBV bufferraren tamaina"
31
@@ -44,34 +42,40 @@
32
 AMF.H264.FillerData="Datu betegarria"
33
 AMF.H264.FrameSkipping="Fotogramen saltoa"
34
 AMF.H264.EnforceHRDCompatibility="Behartu HRD bateragarritasuna"
35
-AMF.H264.MaximumAccessUnitSize="Sarbide unitatearen gehienezko tamaina"
36
 AMF.H264.KeyframeInterval="Gako fotogramen tartea"
37
 AMF.H264.IDRPeriod="IDR periodoa"
38
-AMF.H264.HeaderInsertionSpacing="Goiburuak txertatzeko tartea"
39
-AMF.H264.BPicture.Pattern="B-Picture eredua"
40
-AMF.H264.BPicture.Reference="B-Picture erreferentzia"
41
 AMF.H264.DeblockingFilter="Desblokeoko iragazkia"
42
-AMF.H264.SlicesPerFrame="Zatiak fotogramako"
43
-AMF.H264.IntraRefreshNumMBsPerSlot="Makroblokeen barne freskatze kopura erreteneko"
44
+AMF.H264.ScanType="Eskaneatze mota"
45
+AMF.H264.ScanType.Description="Erabili behar den eskaneatze metodoa, utzi beti '\@AMF.H264.ScanType.Progressive\@'."
46
+AMF.H264.ScanType.Progressive="Progresiboa"
47
+AMF.H264.ScanType.Interlaced="Gurutzelarkatua"
48
 AMF.H264.MotionEstimation="Mugimenduaren estimazioa"
49
 AMF.H264.MotionEstimation.None="Ezer ez"
50
 AMF.H264.MotionEstimation.Half="Pixel erdia"
51
 AMF.H264.MotionEstimation.Quarter="Pixel laurdena"
52
 AMF.H264.MotionEstimation.Both="Pixel erdia eta laurdena"
53
-AMF.H264.Device="Gailua"
54
-AMF.H264.Device.Description="Zein gailu erabili kodeketarako.\nHautatutako memoria mota ez du 'Host' izan behar."
55
-AMF.H264.UseOpenCL="Erabili OpenCL"
56
-AMF.H264.UseOpenCL.Description="Kodifikagailuak OpenCL erabili behar du banakako fotogramak bidaltzeko?"
57
+AMF.H264.CodingType="Kodetze mota"
58
+AMF.H264.MaximumLTRFrames="Gehienezko LTR fotogramak"
59
+AMF.H264.MaximumAccessUnitSize="Sarbide unitatearen gehienezko tamaina"
60
+AMF.H264.HeaderInsertionSpacing="Goiburuak txertatzeko tartea"
61
+AMF.H264.WaitForTask.Description="Ezezaguna, esperimentala"
62
+AMF.H264.PreAnalysisPass.Description="Ezezaguna, esperimentala"
63
+AMF.H264.VBAQ.Description="Ezezaguna, esperimentala"
64
+AMF.H264.GOPSize.Description="Ezezaguna, esperimentala"
65
+AMF.H264.GOPAlignment.Description="Ezezaguna, esperimentala"
66
+AMF.H264.MaximumReferenceFrames.Description="Ezezaguna, esperimentala"
67
+AMF.H264.SlicesPerFrame="Zatiak fotogramako"
68
+AMF.H264.SliceMode.Description="Ezezaguna, esperimentala"
69
+AMF.H264.MaximumSliceSize.Description="Ezezaguna, esperimentala"
70
+AMF.H264.SliceControlMode.Description="Ezezaguna, esperimentala"
71
+AMF.H264.SliceControlSize.Description="Ezezaguna, esperimentala"
72
+AMF.H264.IntraRefresh.NumberOfStripes.Description="Ezezaguna, esperimentala"
73
+AMF.H264.OpenCL="OpenCL"
74
 AMF.H264.View="Ikuspegia"
75
 AMF.H264.View.Description="Zein propietate ikusi behar dira. Ez duzu laguntzarik jasoko 'Aditu' edo 'Maisu' ikuspegian."
76
 AMF.H264.View.Basic="Oinarrizkoa"
77
 AMF.H264.View.Advanced="Aurreratua"
78
 AMF.H264.View.Expert="Aditu"
79
 AMF.H264.View.Master="Maixu"
80
-AMF.H264.UnlockProperties="Desblokeatu propietateak"
81
 AMF.H264.Debug="Garbiketa"
82
-AMF.Util.Default="Lehenetsia"
83
-AMF.Util.Automatic="Automatikoa"
84
-AMF.Util.Manual="Eskuz"
85
-AMF.Util.Toggle.Disabled="Ezgaituta"
86
-AMF.Util.Toggle.Enabled="Gaituta"
87
+
88
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/fi-FI.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/fi-FI.ini Changed
52
 
1
@@ -1,3 +1,8 @@
2
+AMF.Util.Default="Oletusarvo"
3
+AMF.Util.Automatic="Automaattinen"
4
+AMF.Util.Manual="Manuaalinen"
5
+AMF.Util.Toggle.Disabled="Pois käytöstä"
6
+AMF.Util.Toggle.Enabled="Käytössä"
7
 AMF.H264.Preset="Esiasetus"
8
 AMF.H264.Preset.ResetToDefaults="Palauta oletukset"
9
 AMF.H264.Preset.Recording="Tallennus"
10
@@ -16,9 +21,6 @@
11
 AMF.H264.QualityPreset.Quality="Laatu"
12
 AMF.H264.Profile="Profiili"
13
 AMF.H264.ProfileLevel="Profiilin taso"
14
-AMF.H264.ScanType="Skannaustyyppi"
15
-AMF.H264.ScanType.Progressive="Progressiivinen"
16
-AMF.H264.ScanType.Interlaced="Lomitettu"
17
 AMF.H264.RateControlMethod="Rate Control -tapa"
18
 AMF.H264.RateControlMethod.CQP="Pysyvä QP (CQP)"
19
 AMF.H264.RateControlMethod.CBR="Jatkuva bitrate (CBR)"
20
@@ -31,16 +33,15 @@
21
 AMF.H264.QP.IFrame="I-Frame QP"
22
 AMF.H264.QP.PFrame="P-Frame QP"
23
 AMF.H264.QP.BFrame="B-Frame QP"
24
-AMF.H264.QP.BPictureDelta="B-Picture Delta QP"
25
-AMF.H264.QP.ReferenceBPictureDelta="Reference B-Picture Delta QP"
26
 AMF.H264.VBVBuffer="VBV-puskuri"
27
 AMF.H264.VBVBuffer.Size="VBV-puskurin koko"
28
 AMF.H264.FillerData="Täyttödata"
29
 AMF.H264.FrameSkipping="Ruudun ohitus"
30
 AMF.H264.EnforceHRDCompatibility="Pakota HRD-yhteensopivuus"
31
-AMF.H264.BPicture.Pattern="B-Picture Pattern"
32
-AMF.H264.BPicture.Reference="B-Picture Reference"
33
 AMF.H264.DeblockingFilter="Deblocking filtteri"
34
+AMF.H264.ScanType="Skannaustyyppi"
35
+AMF.H264.ScanType.Progressive="Progressiivinen"
36
+AMF.H264.ScanType.Interlaced="Lomitettu"
37
 AMF.H264.MotionEstimation="Liikkeen ennakointi"
38
 AMF.H264.MotionEstimation.None="Ei mitään"
39
 AMF.H264.View="Näyttötila"
40
@@ -48,10 +49,5 @@
41
 AMF.H264.View.Advanced="Kehittynyt"
42
 AMF.H264.View.Expert="Expertti"
43
 AMF.H264.View.Master="Jumalallinen"
44
-AMF.H264.UnlockProperties="Avaa ominaisuudet"
45
 AMF.H264.Debug="Debug"
46
-AMF.Util.Default="Oletusarvo"
47
-AMF.Util.Automatic="Automaattinen"
48
-AMF.Util.Manual="Manuaalinen"
49
-AMF.Util.Toggle.Disabled="Pois käytöstä"
50
-AMF.Util.Toggle.Enabled="Käytössä"
51
+
52
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/fr-FR.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/fr-FR.ini Changed
92
 
1
@@ -1,3 +1,8 @@
2
+AMF.Util.Default="Défaut"
3
+AMF.Util.Automatic="Automatique"
4
+AMF.Util.Manual="Manuel"
5
+AMF.Util.Toggle.Disabled="Désactivé"
6
+AMF.Util.Toggle.Enabled="Activé"
7
 AMF.H264.Preset="Préréglage"
8
 AMF.H264.Preset.ResetToDefaults="Valeurs par défaut"
9
 AMF.H264.Preset.Recording="Enregistrement"
10
@@ -20,63 +25,57 @@
11
 AMF.H264.Profile.Description="Le profil H.264 utilisé pour l'encodage :\n- 'Baseline' est compatible avec la majorité des lecteurs,\n-'Main' est compatible avec les lecteurs d'ancienne génération (recommandé pour les lecteurs mobiles),\n- 'High' est compatible avec la plupart des lecteurs récents (réglage recommandé pour la plupart des cas)."
12
 AMF.H264.ProfileLevel="Niveau de profil"
13
 AMF.H264.ProfileLevel.Description="Quel niveau de profil H.264 utiliser pour l'encodage :\n- \"Automatique\" laisse l'encodeur déterminer le meilleur profil en fonction de la résolution d'image et du nombre d'images par seconde.\n- \"4.1\" supporte les formats suivants : 1920x1080 30FPS, 1280x720 60FPS, 960x540 90FPS\n- \"4.2\" supporte les formats suivants : 1920x1080 60FPS, 1280x720 120FPS, 960x540 172FPS\n- \"5.0\" supporte les formats suivants : 1920x1080 60FPS, 1280x720 144FPS, 960x540 172FPS\n- \"5.1\" supporte les formats suivants : 3840x2160 30FPS, 1920x1080 120FPS, 1280x720 172FPS, 960x540 172FPS\n- \"5.2\" supporte les formats suivants : 3840x2160 60FPS, 1920x1080 172FPS, 1280x720 172FPS, 960x540 172FPS"
14
-AMF.H264.MaximumLTRFrames="Maximum de trames LTR"
15
-AMF.H264.MaximumLTRFrames.Description="Les trames LTR (Long Term Reference) sont une fonctionnalité de l'encodeur qui l'autorise à marquer certaines trames comme étant des trames de référence au sein d'une séquence d'images.\nUtiliser cette fonctionnalité peut apporter un gain de qualité dans le cas où les images B (B-Pictures) ne sont pas supportées ou activées.\nLes trames LTR ne sont pas utilisables en conjonction des images B, et l'encodeur désactivera les images B si cette fonctionnalité (trames LTR) est activée."
16
-AMF.H264.ScanType="Balayage"
17
-AMF.H264.ScanType.Description="La méthode de balayage à utiliser (laissez cette valeur sur \"\@AMF.H264.ScanType.Progressive\@\")."
18
-AMF.H264.ScanType.Progressive="Progressif"
19
-AMF.H264.ScanType.Interlaced="Entrelacé"
20
 AMF.H264.RateControlMethod="Méthode de contrôle du débit"
21
 AMF.H264.RateControlMethod.CQP="QP constant (CQP)"
22
 AMF.H264.RateControlMethod.CBR="Débit constant (CBR)"
23
 AMF.H264.RateControlMethod.VBR.Peak="Débit Variable (maximum) (VBR)"
24
 AMF.H264.RateControlMethod.VBR.Latency="Débit Variable (latence limitée) (VBR_LAT)"
25
 AMF.H264.Bitrate.Target="Débit cible"
26
+AMF.H264.Bitrate.Target.Description="Le débit de données sortantes que l'encodeur va essayer de respecter pendant l'encodage."
27
 AMF.H264.Bitrate.Peak="Débit maximal"
28
+AMF.H264.Bitrate.Peak.Description="Le débit de données sortantes que l'encodeur va essayer de respecter pendant l'encodage."
29
 AMF.H264.QP.Minimum="QP minimal"
30
 AMF.H264.QP.Maximum="QP maximal"
31
 AMF.H264.QP.IFrame="QP I-Frame"
32
 AMF.H264.QP.PFrame="QP P-Frame"
33
 AMF.H264.QP.BFrame="QP B-Frame"
34
-AMF.H264.QP.BPictureDelta="QP B-Image Delta"
35
-AMF.H264.QP.ReferenceBPictureDelta="Delta QP de l'image B de référence"
36
 AMF.H264.VBVBuffer="Tampon VBV"
37
+AMF.H264.VBVBuffer.Description="Quelle méthode utiliser pour déterminer la taille du tampon VBV :\n- \"\@AMF.Util.Automatic\@\" calcule la taille en fonction de la valeur de respect du tampon,\n- \"\@AMF.Util.Manual\@\" laisse le choix de la taille à l'utilisateur.\nLe tampon VBV (Video Buffering Verifier) est utilisé par certaines méthodes de contrôle du débit pour assurer au mieux le respect des contraintes données."
38
 AMF.H264.VBVBuffer.Strictness="Respect du tampon VBV"
39
 AMF.H264.VBVBuffer.Size="Taille du tampon VBV"
40
 AMF.H264.VBVBuffer.Fullness="Remplissage du tampon VBV"
41
 AMF.H264.FillerData="Données de remplissage"
42
 AMF.H264.FrameSkipping="Saut d'images"
43
 AMF.H264.EnforceHRDCompatibility="Appliquer la compatibilité avec l'HRD"
44
-AMF.H264.MaximumAccessUnitSize="Taille max. d'une Access Unit"
45
 AMF.H264.KeyframeInterval="Intervalle d'images-clé"
46
 AMF.H264.IDRPeriod="Périodicité des trames IDR"
47
-AMF.H264.HeaderInsertionSpacing="Intervalle d'insertion de l'en-tête de stream"
48
-AMF.H264.BPicture.Pattern="Modèle d'image B"
49
-AMF.H264.BPicture.Reference="Référence d'image B"
50
 AMF.H264.DeblockingFilter="Filtre de dégroupage"
51
-AMF.H264.SlicesPerFrame="Tranches par image"
52
+AMF.H264.ScanType="Balayage"
53
+AMF.H264.ScanType.Description="La méthode de balayage à utiliser (laissez cette valeur sur \"\@AMF.H264.ScanType.Progressive\@\")."
54
+AMF.H264.ScanType.Progressive="Progressif"
55
+AMF.H264.ScanType.Interlaced="Entrelacé"
56
 AMF.H264.MotionEstimation="Estimation de mouvement"
57
 AMF.H264.MotionEstimation.Description="L'estimation du mouvement permet à l'encodeur de réduire le débit en calculant le déplacement des pixels."
58
 AMF.H264.MotionEstimation.None="Aucun"
59
 AMF.H264.MotionEstimation.Half="Demi-pixel"
60
 AMF.H264.MotionEstimation.Quarter="Quart de pixel"
61
 AMF.H264.MotionEstimation.Both="Demi-pixel & quart de pixel"
62
-AMF.H264.Device="Périphérique"
63
-AMF.H264.Device.Description="Quel périphérique utiliser pour l'encodage.\n<Seulement dans le cas où \"Type de mémoire\" n'est pas réglé sur \"Hôte\"."
64
-AMF.H264.UseOpenCL="OpenCL"
65
-AMF.H264.UseOpenCL.Description="L'encodeur doit-il utiliser OpenCL pour transmettre chaque image ?"
66
+AMF.H264.CodingType="Type de codage"
67
+AMF.H264.CodingType.Description="Le type de codage à utiliser:\n* \"\@AMF.Util.Default\@\" : laisser AMF décider (recommandé).\n* CALVC (Context-Adaptive Variable-Length Coding) est rapide mais lourd.\n* CABAC (Context-Adaptive Binary Arithmetic Coding) est lent mais léger."
68
+AMF.H264.MaximumLTRFrames="Maximum de trames LTR"
69
+AMF.H264.MaximumAccessUnitSize="Taille max. d'une Access Unit"
70
+AMF.H264.MaximumAccessUnitSize.Description="Taille maximale d’une unité d’accès pour un NAL. Une valeur de 0 permet à l’encodeur de choisir le meilleur."
71
+AMF.H264.HeaderInsertionSpacing="Intervalle d'insertion de l'en-tête de stream"
72
+AMF.H264.SlicesPerFrame="Tranches par image"
73
+AMF.H264.VideoAPI="API vidéo"
74
+AMF.H264.VideoAdapter="Périphérique vidéo"
75
+AMF.H264.OpenCL="OpenCL"
76
 AMF.H264.View="Mode de visualisation"
77
 AMF.H264.View.Description="Quels paramètres afficher ?\nChoisir '\@AMF.H264.View.Master\@' est réservé aux utilisateurs avancés, et vous exclus d'office de toute possibilité d'assistance de la part du développeur."
78
 AMF.H264.View.Basic="Basique"
79
 AMF.H264.View.Advanced="Avancé"
80
 AMF.H264.View.Expert="Expert"
81
 AMF.H264.View.Master="Maître"
82
-AMF.H264.UnlockProperties="Débloquer les propriétés"
83
-AMF.H264.UnlockProperties.Description="Sur certains paramètres, débloque au maximum la plage des valeurs possibles plutôt que de la limiter à une plage partielle."
84
 AMF.H264.Debug="Débogage"
85
 AMF.H264.Debug.Description="Activer le débogage avancé dans le fichier journal (dans le cas où vous souhaitez solliciter une assistance auprès du développeur de l'encodeur)."
86
-AMF.Util.Default="Défaut"
87
-AMF.Util.Automatic="Automatique"
88
-AMF.Util.Manual="Manuel"
89
-AMF.Util.Toggle.Disabled="Désactivé"
90
-AMF.Util.Toggle.Enabled="Activé"
91
+
92
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/hr-HR.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/hr-HR.ini Changed
39
 
1
@@ -1,3 +1,7 @@
2
+AMF.Util.Default="Podrazumevano"
3
+AMF.Util.Automatic="Automatski"
4
+AMF.Util.Toggle.Disabled="Onemogućeno"
5
+AMF.Util.Toggle.Enabled="Omogućeno"
6
 AMF.H264.Usage.Transcoding="Transkodiranje"
7
 AMF.H264.Usage.UltraLowLatency="Ultra nisko kašnjenje"
8
 AMF.H264.Usage.LowLatency="Nisko kašnjenje"
9
@@ -7,9 +11,6 @@
10
 AMF.H264.QualityPreset.Quality="Kvalitet"
11
 AMF.H264.Profile="Profil"
12
 AMF.H264.ProfileLevel="Nivo profila"
13
-AMF.H264.ScanType="Vrsta skeniranja"
14
-AMF.H264.ScanType.Progressive="Progresivno"
15
-AMF.H264.ScanType.Interlaced="Isprekidano"
16
 AMF.H264.RateControlMethod="Metoda kontrole protoka"
17
 AMF.H264.RateControlMethod.CQP="Konstantan kvalitet (CQP)"
18
 AMF.H264.RateControlMethod.CBR="Konstantan protok (CBR)"
19
@@ -22,15 +23,11 @@
20
 AMF.H264.QP.IFrame="I-Frejm QP"
21
 AMF.H264.QP.PFrame="P-Frejm QP"
22
 AMF.H264.QP.BFrame="B-Frejm QP"
23
-AMF.H264.QP.BPictureDelta="B-Promena slike QP"
24
-AMF.H264.QP.ReferenceBPictureDelta="Referenca B-Promena slike QP"
25
 AMF.H264.FillerData="Data za popunjavanje"
26
 AMF.H264.FrameSkipping="Preskakanje frejmova"
27
 AMF.H264.EnforceHRDCompatibility="Prisilna HRD kompatibilnost"
28
-AMF.H264.BPicture.Pattern="B-Šablonska slika"
29
-AMF.H264.BPicture.Reference="B-Referentna slika"
30
 AMF.H264.DeblockingFilter="Odblokirajući filter"
31
-AMF.Util.Default="Podrazumevano"
32
-AMF.Util.Automatic="Automatski"
33
-AMF.Util.Toggle.Disabled="Onemogućeno"
34
-AMF.Util.Toggle.Enabled="Omogućeno"
35
+AMF.H264.ScanType="Vrsta skeniranja"
36
+AMF.H264.ScanType.Progressive="Progresivno"
37
+AMF.H264.ScanType.Interlaced="Isprekidano"
38
+
39
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/hu-HU.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/hu-HU.ini Changed
97
 
1
@@ -1,3 +1,8 @@
2
+AMF.Util.Default="Alapértelmezett"
3
+AMF.Util.Automatic="Automatikus"
4
+AMF.Util.Manual="Manuális"
5
+AMF.Util.Toggle.Disabled="Letiltva"
6
+AMF.Util.Toggle.Enabled="Engedélyezve"
7
 AMF.H264.Preset="Készlet"
8
 AMF.H264.Preset.ResetToDefaults="Alapértelmezett beállítások visszaállítása"
9
 AMF.H264.Preset.Recording="Felvétel"
10
@@ -17,10 +22,6 @@
11
 AMF.H264.Profile="Enkóder profil"
12
 AMF.H264.Profile.Description="Mely H.264 Profilt használja kódoláshoz:\n- 'Baseline' a legnagyobb platform támogatottsággal,\n- 'Main' a régebbi eszközök támogatják (ajánlott ha mobil eszköz tulajdonosokat céloz meg),\n- 'High' a jelenlegi eszközök támogatják (ajánlott)."
13
 AMF.H264.ProfileLevel="Profil szint"
14
-AMF.H264.MaximumLTRFrames="Maximális LTR képkocka"
15
-AMF.H264.ScanType="Rögzítés módja"
16
-AMF.H264.ScanType.Progressive="Progreszív"
17
-AMF.H264.ScanType.Interlaced="Interlaced (Kísérleti)"
18
 AMF.H264.RateControlMethod="Bitráta vezérlés"
19
 AMF.H264.RateControlMethod.CQP="Erőltetett QP (CQP)"
20
 AMF.H264.RateControlMethod.CBR="Konstans bitráta (CBR)"
21
@@ -35,46 +36,57 @@
22
 AMF.H264.QP.Maximum="Maximum QP"
23
 AMF.H264.QP.Maximum.Description="Legmagasabb QP (Quantization Parameter) képkockában használható érték."
24
 AMF.H264.QP.IFrame="I-Képkocka QP"
25
-AMF.H264.QP.IFrame.Description="Rögzített QP (Quantization Parameter) érték használata az I-Képkockákhoz.\nI-Képkocka QP értéknek nagyobbnak kell lennie a P- és B-Képkocka QP értéknél."
26
+AMF.H264.QP.IFrame.Description="Rögzített QP érték az I képkockák használatához."
27
 AMF.H264.QP.PFrame="P-Képkocka QP"
28
-AMF.H264.QP.PFrame.Description="Rögzített QP (Quantization Parameter) érték használata a P-Képkockákhoz.\nIPKépkocka QP értéknek nagyobbnak kell lennie a B-Képkocka QP értéknél."
29
+AMF.H264.QP.PFrame.Description="Rögzített QP érték a P képkockák használatához."
30
 AMF.H264.QP.BFrame="B-Képkocka QP"
31
 AMF.H264.QP.BFrame.Description="Rögzített QP (Quantization Parameter) érték a B-Képkockák használatához."
32
-AMF.H264.QP.BPictureDelta="B-Képkocka Delta QP"
33
-AMF.H264.QP.BPictureDelta.Description="Delta QP (Quantization Parameter) érték az utolsó nem referencia a B-Képhez."
34
-AMF.H264.QP.ReferenceBPictureDelta="Referencia B-képkocka Delta QP"
35
-AMF.H264.QP.ReferenceBPictureDelta.Description="Delta QP (Quantization Parameter) érték az utolsó referencia a B-Képhez."
36
 AMF.H264.VBVBuffer="VBV puffer"
37
 AMF.H264.VBVBuffer.Strictness="VBV Puffer kötöttség"
38
+AMF.H264.VBVBuffer.Strictness.Description="Meghatározza a VBV puffer szigorúságát, 100% esetén teljesen pontos és 0% esetén kötetlen."
39
 AMF.H264.VBVBuffer.Size="VBV pufferméret"
40
 AMF.H264.VBVBuffer.Fullness="VBV puffer telítettség"
41
 AMF.H264.FillerData="Filler adat"
42
 AMF.H264.FrameSkipping="Képkocka kihagyás"
43
 AMF.H264.EnforceHRDCompatibility="HRD Kompatibilitás kényszerítése"
44
-AMF.H264.MaximumAccessUnitSize="Hozzáférési egység maximális mérete"
45
 AMF.H264.KeyframeInterval="Kulcsképkocka időköze"
46
 AMF.H264.IDRPeriod="IDR időköz"
47
-AMF.H264.BPicture.Pattern="B-képkockák száma"
48
-AMF.H264.BPicture.Reference="B-képkocka referencia"
49
+AMF.H264.BFrame.Pattern="B képkocka"
50
+AMF.H264.BFrame.DeltaQP="B képkocka Delta QP"
51
+AMF.H264.BFrame.Reference="Referenciálható B képkockák"
52
+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."
53
+AMF.H264.BFrame.ReferenceDeltaQP="Delta QP a referenciálható B kockákhoz"
54
+AMF.H264.BFrame.ReferenceDeltaQP.Description="Delta QP érték az utolsó I vagy P képkockának a referenciálható B képkockákhoz."
55
 AMF.H264.DeblockingFilter="Deblocking Filter"
56
-AMF.H264.SlicesPerFrame="Szeletelés képkockánként"
57
+AMF.H264.ScanType="Rögzítés módja"
58
+AMF.H264.ScanType.Progressive="Progresszív"
59
+AMF.H264.ScanType.Interlaced="Váltottsoros (Kísérleti)"
60
 AMF.H264.MotionEstimation="Mozgásbecslés"
61
 AMF.H264.MotionEstimation.None="Semmi"
62
 AMF.H264.MotionEstimation.Half="Fél-pixel"
63
 AMF.H264.MotionEstimation.Quarter="Negyed-pixel"
64
 AMF.H264.MotionEstimation.Both="Fél-&negyed-pixel"
65
-AMF.H264.Device="Eszköz"
66
-AMF.H264.UseOpenCL="OpenCL Használata"
67
+AMF.H264.CodingType="Kódolás típusa"
68
+AMF.H264.MaximumLTRFrames="Maximális LTR képkocka"
69
+AMF.H264.MaximumAccessUnitSize="Hozzáférési egység maximális mérete"
70
+AMF.H264.PreAnalysisPass="Elemzés előtti fázis"
71
+AMF.H264.VBAQ="VBAQ"
72
+AMF.H264.GOPSize="GOP méret"
73
+AMF.H264.GOPAlignment="GOP igazítás"
74
+AMF.H264.MaximumReferenceFrames="Maximális referencia képkockák"
75
+AMF.H264.SlicesPerFrame="Szeletelés képkockánként"
76
+AMF.H264.SliceMode="Szelet mód"
77
+AMF.H264.MaximumSliceSize="Maximális szeletméret"
78
+AMF.H264.VideoAPI="Videó API"
79
+AMF.H264.VideoAPI.Description="Melyik API használható kódoláshoz."
80
+AMF.H264.VideoAdapter="Videó adapter"
81
+AMF.H264.VideoAdapter.Description="Melyik adapter használható kódoláshoz."
82
+AMF.H264.OpenCL="OpenCL"
83
 AMF.H264.View="Nézet mód"
84
 AMF.H264.View.Basic="Alap"
85
 AMF.H264.View.Advanced="Haladó"
86
 AMF.H264.View.Expert="Szakértő"
87
 AMF.H264.View.Master="Mester"
88
-AMF.H264.UnlockProperties="Tulajdonságok feloldása"
89
 AMF.H264.Debug="Hibakeresés"
90
 AMF.H264.Debug.Description="További hibakeresési naplózás engedélyezése, aktiválja amennyiben tanácsadásra van szüksége a kódolóval kapcsolatban."
91
-AMF.Util.Default="Alapértelmezett"
92
-AMF.Util.Automatic="Automatikus"
93
-AMF.Util.Manual="Manuális"
94
-AMF.Util.Toggle.Disabled="Letiltva"
95
-AMF.Util.Toggle.Enabled="Engedélyezve"
96
+
97
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/it-IT.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/it-IT.ini Changed
78
 
1
@@ -1,3 +1,8 @@
2
+AMF.Util.Default="Predefinito"
3
+AMF.Util.Automatic="Automatico"
4
+AMF.Util.Manual="Manuale"
5
+AMF.Util.Toggle.Disabled="Disabilitato"
6
+AMF.Util.Toggle.Enabled="Attivo"
7
 AMF.H264.Preset="Preset"
8
 AMF.H264.Preset.ResetToDefaults="Ripristina a Predefiniti"
9
 AMF.H264.Preset.Recording="Registrazione"
10
@@ -17,10 +22,6 @@
11
 AMF.H264.Profile="Profilo"
12
 AMF.H264.ProfileLevel="Livello profilo"
13
 AMF.H264.ProfileLevel.Description="Quale livello di profilo H.264 usare per l'encoding:\n- 'Automatico' calcola il miglior livello per il dato Frame Rate e Frame Size,\n- '4.1' supporta 1920x1080 30FPS, 1280x720 60FPS, 960x540 90FPS\n- '4.2' supporta 1920x1080 60FPS, 1280x720 120FPS, 960x540 172FPS\n- '5.0' supporta 1920x1080 60FPS, 1280x720 144FPS, 960x540 172FPS\n- '5.1' supporta 3840x2160 30FPS, 1920x1080 120FPS, 1280x720 172FPS, 960x540 172FPS\n- '5.2' supporta 3840x2160 60FPS, 1920x1080 172FPS, 1280x720 172FPS, 960x540 172FPS"
14
-AMF.H264.MaximumLTRFrames="Fotogrammi LTR Massimi"
15
-AMF.H264.ScanType="Tipo di scansione"
16
-AMF.H264.ScanType.Progressive="Progressivo"
17
-AMF.H264.ScanType.Interlaced="Interlacciato"
18
 AMF.H264.RateControlMethod="Metodo di controllo della frequenza"
19
 AMF.H264.RateControlMethod.CQP="QP Costante (QPC)"
20
 AMF.H264.RateControlMethod.CBR="Bitrate costante (CBR)"
21
@@ -29,12 +30,12 @@
22
 AMF.H264.Bitrate.Target="Bitrate di destinazione"
23
 AMF.H264.Bitrate.Peak="Picco Bitrate"
24
 AMF.H264.QP.Minimum="QP Minimo"
25
+AMF.H264.QP.Minimum.Description="Valore QP più basso da utilizzare in un Frame."
26
 AMF.H264.QP.Maximum="QP Massimo"
27
+AMF.H264.QP.Maximum.Description="Valore QP più alto da utilizzare in un Frame."
28
 AMF.H264.QP.IFrame="I-Frame QP"
29
 AMF.H264.QP.PFrame="P-Frame QP"
30
 AMF.H264.QP.BFrame="B-Frame QP"
31
-AMF.H264.QP.BPictureDelta="B-Picture Delta QP"
32
-AMF.H264.QP.ReferenceBPictureDelta="Riferimento B-Picture Delta QP"
33
 AMF.H264.VBVBuffer="Buffer VBV"
34
 AMF.H264.VBVBuffer.Strictness="Strettezza Buffer VBV"
35
 AMF.H264.VBVBuffer.Size="Dimensione Buffer VBV"
36
@@ -42,31 +43,27 @@
37
 AMF.H264.FillerData="Dati di riempimento"
38
 AMF.H264.FrameSkipping="Frame Skipping"
39
 AMF.H264.EnforceHRDCompatibility="Forza compatibilità HRD"
40
-AMF.H264.MaximumAccessUnitSize="Massima dimensione di unità d'accesso"
41
 AMF.H264.KeyframeInterval="Intervallo Keyframe"
42
 AMF.H264.IDRPeriod="Periodo IDR"
43
-AMF.H264.HeaderInsertionSpacing="Spaziatura di inserimento di intestazione"
44
-AMF.H264.BPicture.Pattern="Modello B-Picture"
45
-AMF.H264.BPicture.Reference="Riferimento B-Picture"
46
 AMF.H264.DeblockingFilter="Filtro di deblock"
47
-AMF.H264.SlicesPerFrame="Slices Per Frame"
48
-AMF.H264.IntraRefreshNumMBsPerSlot="Intra-Refresh Number of Macroblocks Per Slot"
49
+AMF.H264.ScanType="Tipo di scansione"
50
+AMF.H264.ScanType.Progressive="Progressivo"
51
+AMF.H264.ScanType.Interlaced="Interlacciato"
52
 AMF.H264.MotionEstimation="Stima Movimento"
53
 AMF.H264.MotionEstimation.None="Nessuno"
54
 AMF.H264.MotionEstimation.Half="Metà-Pixel"
55
 AMF.H264.MotionEstimation.Quarter="Quarto-Pixel"
56
 AMF.H264.MotionEstimation.Both="Meta- & Quarto-Pixel"
57
-AMF.H264.Device="Dispositivo"
58
-AMF.H264.UseOpenCL="OpenCL"
59
+AMF.H264.CodingType="Tipo di codifica"
60
+AMF.H264.MaximumLTRFrames="Fotogrammi LTR Massimi"
61
+AMF.H264.MaximumAccessUnitSize="Massima dimensione di unità d'accesso"
62
+AMF.H264.HeaderInsertionSpacing="Spaziatura di inserimento di intestazione"
63
+AMF.H264.WaitForTask="Attendere per attività"
64
+AMF.H264.SlicesPerFrame="Slices Per Frame"
65
 AMF.H264.View="Modalità di visualizzazione"
66
 AMF.H264.View.Basic="Basico"
67
 AMF.H264.View.Advanced="Avanzate"
68
 AMF.H264.View.Expert="Esperto"
69
 AMF.H264.View.Master="Master"
70
-AMF.H264.UnlockProperties="Sblocca proprietà"
71
 AMF.H264.Debug="Debug"
72
-AMF.Util.Default="Predefinito"
73
-AMF.Util.Automatic="Automatico"
74
-AMF.Util.Manual="Manuale"
75
-AMF.Util.Toggle.Disabled="Disabilitato"
76
-AMF.Util.Toggle.Enabled="Attivo"
77
+
78
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/ja-JP.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/ja-JP.ini Changed
157
 
1
@@ -1,3 +1,8 @@
2
+AMF.Util.Default="既定値"
3
+AMF.Util.Automatic="自動"
4
+AMF.Util.Manual="手動"
5
+AMF.Util.Toggle.Disabled="無効"
6
+AMF.Util.Toggle.Enabled="有効"
7
 AMF.H264.Preset="プリセット"
8
 AMF.H264.Preset.ResetToDefaults="既定値に戻す"
9
 AMF.H264.Preset.Recording="録画中"
10
@@ -7,27 +12,27 @@
11
 AMF.H264.Preset.Twitch="Twitch"
12
 AMF.H264.Preset.YouTube="YouTube"
13
 AMF.H264.Usage="用途"
14
+AMF.H264.Usage.Description="AMFの使用方法:\n- '\@AMF.H264.Usage.Transcoding\@' は汎用のトランスコード (推奨) で、\n- '\@AMF.H264.Usage.UltraLowLatency\@' は超低遅延エンコード用で、\n- '\@AMF.H264.Usage.LowLatency\@' は上記と似ていますが少し遅延があります。\n配信は '\@AMF.H264.Usage.Transcoding\@' のみをサポートし、他のすべての値は録画で使用できます。"
15
 AMF.H264.Usage.Transcoding="変換"
16
 AMF.H264.Usage.UltraLowLatency="超低遅延"
17
 AMF.H264.Usage.LowLatency="低遅延"
18
 AMF.H264.QualityPreset="品質プリセット"
19
+AMF.H264.QualityPreset.Description="どの品質プリセットをAMFが目標とするか:\n- '\@AMF.H264.QualityPreset.Speed\@' は最速ですが品質は最悪で、\n- '\@AMF.H264.QualityPreset.Balanced\@' は両方のバランスの取れた組み合わせで、\n- '\@AMF.H264.QualityPreset.Quality\@' は指定されたビットレートに対して最高の品質を提供します。"
20
 AMF.H264.QualityPreset.Speed="速度"
21
 AMF.H264.QualityPreset.Balanced="バランス"
22
 AMF.H264.QualityPreset.Quality="品質"
23
 AMF.H264.Profile="プロファイル"
24
+AMF.H264.Profile.Description="エンコードに使用するH.264プロファイル:\n- 'Baseline' はプラットフォームごとのサポートが最も大きく、\n- 'Main' は古いデバイスでもサポートされ、(モバイルデバイスがターゲットなら推奨)\n- 'High' は現在主流のデバイスでサポートされています。(推奨)"
25
 AMF.H264.ProfileLevel="プロファイルレベル"
26
 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、1920 x 1080 172FPS, 1280 x 720 172FPS, 960 x 540 172FPS をサポートします。"
27
-AMF.H264.MaximumLTRFrames="最大 LTR フレーム"
28
-AMF.H264.ScanType="スキャンの種類"
29
-AMF.H264.ScanType.Description="どのスキャン方法が使用されるか、'プログレッシブ'を常にこのままにしておきます。"
30
-AMF.H264.ScanType.Progressive="プログレッシブ"
31
-AMF.H264.ScanType.Interlaced="インターレース"
32
 AMF.H264.RateControlMethod="レート制御方式"
33
+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遅延と負荷が許可されている場合は目標ビットレートに近く、それ以外の場合はより高いビットレートを使用します (録画に推奨)。"
34
 AMF.H264.RateControlMethod.CQP="固定QP (CQP)"
35
 AMF.H264.RateControlMethod.CBR="固定ビットレート (CBR)"
36
 AMF.H264.RateControlMethod.VBR.Peak="可変ビットレート (ピーク制約) (VBR)"
37
 AMF.H264.RateControlMethod.VBR.Latency="可変ビットレート (遅延制約) (VBR_LAT)"
38
 AMF.H264.Bitrate.Target="目標ビットレート"
39
+AMF.H264.Bitrate.Target.Description="全体的なシーケンスで達成しようとするビットレート。"
40
 AMF.H264.Bitrate.Peak="最大ビットレート"
41
 AMF.H264.Bitrate.Peak.Description="全体的なシーケンスでピークを最大にしようとするビットレート。"
42
 AMF.H264.QP.Minimum="最小QP"
43
@@ -35,49 +40,95 @@
44
 AMF.H264.QP.Maximum="最大QP"
45
 AMF.H264.QP.Maximum.Description="フレームで使用する最高 QP (量子化パラメーター) の値です。"
46
 AMF.H264.QP.IFrame="I-フレーム QP"
47
+AMF.H264.QP.IFrame.Description="I-フレームに使用する固定 QP の値。"
48
 AMF.H264.QP.PFrame="P-フレーム QP"
49
+AMF.H264.QP.PFrame.Description="P-フレームに使用する固定 QP の値。"
50
 AMF.H264.QP.BFrame="B-フレーム QP"
51
-AMF.H264.QP.BPictureDelta="B-画像デルタ QP"
52
-AMF.H264.QP.BPictureDelta.Description="最後の非参照B-画像のデルタQPです。"
53
-AMF.H264.QP.ReferenceBPictureDelta="B-画像参照のデルタQP"
54
-AMF.H264.QP.ReferenceBPictureDelta.Description="最後の参照B-画像のデルタQPです。"
55
+AMF.H264.QP.BFrame.Description="B-フレームに対して使用する固定 QP (量子化パラメーター) の値です。"
56
 AMF.H264.VBVBuffer="VBV バッファ"
57
+AMF.H264.VBVBuffer.Description="どの方法を使用してVBVバッファーサイズを決定する必要があるか:\n- '\@AMF.Util.Automatic\@' は厳密性制約を使用してサイズを計算し、\n- '\@AMF.Util.Manual\@' はユーザーがサイズを制御できるようにします。\nVBV (ビデオバッファリングベリファイア) バッファは特定のレート制御方法により指定された制約内で全体のビットレートを保持するために使用されます。"
58
 AMF.H264.VBVBuffer.Strictness="VBV バッファ厳密性"
59
+AMF.H264.VBVBuffer.Strictness.Description="VBV バッファーの厳密さを決定し、100%は可能な限り厳密で0%は制限されません。"
60
 AMF.H264.VBVBuffer.Size="VBV バッファサイズ"
61
+AMF.H264.VBVBuffer.Size.Description="シーケンスにおけるビットレート制御のために使用されている VBV バッファーのサイズ。"
62
 AMF.H264.VBVBuffer.Fullness="VBV バッファ充満"
63
+AMF.H264.VBVBuffer.Fullness.Description="VBVバッファーの初期状態は、エンコーディングの初期シーケンスにのみ影響します。"
64
 AMF.H264.FillerData="フィラーデータ"
65
+AMF.H264.FillerData.Description="フィラーデータを有効にするとエンコーダは空の情報でシーケンスの残りのスペースを埋めることによって少なくともターゲットビットレートを維持することができます。"
66
 AMF.H264.FrameSkipping="フレームスキップ"
67
+AMF.H264.FrameSkipping.Description="フレームスキッピングはエンコーダが目標ビットレート要件を満たすためにフレームをドロップすることを可能にする。\nエンコーダがフレームを落とすときに代わりにリピートラストフレームNALをストリームに挿入する。\n目標ビットレートが非常に低い場合に役立ちます。"
68
 AMF.H264.EnforceHRDCompatibility="HRD 互換性を強制"
69
-AMF.H264.MaximumAccessUnitSize="最大アクセスユニットサイズ"
70
+AMF.H264.EnforceHRDCompatibility.Description="フレーム内の最大QP値の変化を制限する仮説的参照デコーダの制限を強制します。\n録画や配信には非推奨で参照ソフトウェアデコーダのみを持つ非常に古いデバイスをターゲットにする場合にのみ使用してください。"
71
 AMF.H264.KeyframeInterval="キーフレーム間隔"
72
 AMF.H264.KeyframeInterval.Description="ドロップ不可能なフレーム間の秒数。\nGOPのサイズも制御します。"
73
 AMF.H264.IDRPeriod="IDR 周期"
74
-AMF.H264.HeaderInsertionSpacing="ヘッダー挿入間隔"
75
-AMF.H264.BPicture.Pattern="B-画像パターン"
76
-AMF.H264.BPicture.Reference="B-画像参照"
77
+AMF.H264.IDRPeriod.Description="フレーム内の瞬時デコードリフレッシュ (IDR) 間の距離を定義します。 GOP-シーケンスのサイズも制御します。"
78
+AMF.H264.BFrame.Pattern="B-フレーム"
79
+AMF.H264.BFrame.Pattern.Description="エンコードに使用するBフレームの数。\n第2世代および第3世代のVCEカードでサポートされています。 エンコーディングのパフォーマンスに悪影響を与えます。"
80
+AMF.H264.BFrame.DeltaQP="B-フレーム デルタ QP"
81
+AMF.H264.BFrame.DeltaQP.Description="参照不可能なB-フレームに対する最後のI-フレームまたはP-フレームまでのデルタ QP の値。"
82
+AMF.H264.BFrame.Reference="参照可能 B-フレーム"
83
+AMF.H264.BFrame.Reference.Description="B-フレームはP-フレームとI-フレームだけでなく、B-フレームも参照として使用できます。"
84
+AMF.H264.BFrame.ReferenceDeltaQP="参照可能 B-フレーム デルタ QP"
85
+AMF.H264.BFrame.ReferenceDeltaQP.Description="参照可能なB-フレームに対する最後のI-フレームまたはP-フレームまでのデルタ QP の値。"
86
 AMF.H264.DeblockingFilter="デブロックフィルタ"
87
 AMF.H264.DeblockingFilter.Description="デコーダがエンコードされたストリームに対してデブロックフィルタの使用を許可されているかのフラグを設定します。"
88
-AMF.H264.SlicesPerFrame="フレームあたりのスライス"
89
-AMF.H264.IntraRefreshNumMBsPerSlot="スロットごとのマクロブロックのイントラリフレッシュ数"
90
+AMF.H264.ScanType="スキャンの種類"
91
+AMF.H264.ScanType.Description="どのスキャン方法が使用されるか、'プログレッシブ'を常にこのままにしておきます。"
92
+AMF.H264.ScanType.Progressive="プログレッシブ"
93
+AMF.H264.ScanType.Interlaced="インターレース"
94
 AMF.H264.MotionEstimation="動き推定"
95
 AMF.H264.MotionEstimation.Description="動き推定はピクセルがどこに移動したかを推定することによってエンコーダが必要とするビットレートを削減します。"
96
 AMF.H264.MotionEstimation.None="未設定"
97
 AMF.H264.MotionEstimation.Half="1/2ピクセル"
98
 AMF.H264.MotionEstimation.Quarter="1/4ピクセル"
99
 AMF.H264.MotionEstimation.Both="ハーフ & クォーターピクセル"
100
-AMF.H264.Device="デバイス"
101
-AMF.H264.UseOpenCL="OpenCL を使用する"
102
+AMF.H264.CodingType="コーディングの種類"
103
+AMF.H264.CodingType.Description="使用するコーディングの種類:\n* \@AMF.Util.Default\@ AMFが決定します。(推奨)\n* CALVC (Context-Adaptive Variable-Length Coding) は高速ですが、容量は大きいです。\n* CABAC (Context-Adaptive Binary Arithmetic Coding) は低速ですが、容量は小さくなります。"
104
+AMF.H264.MaximumLTRFrames="最大 LTR フレーム"
105
+AMF.H264.MaximumLTRFrames.Description="長期間参照 (LTR) フレームはエンコーダがシーケンス内の特定のフレームに長期間参照可能なフラグを立てる機能です。\nLTRフレームはB-ピクチャとの併用は不可でエンコーダはB-ピクチャが使用されている場合は無効にします。"
106
+AMF.H264.MaximumAccessUnitSize="最大アクセスユニットサイズ"
107
+AMF.H264.MaximumAccessUnitSize.Description="NALに対するアクセス単位の最大サイズ。 値が0の場合エンコーダは最良のものを選択できます。"
108
+AMF.H264.HeaderInsertionSpacing="ヘッダー挿入間隔"
109
+AMF.H264.HeaderInsertionSpacing.Description="NALヘッダーの間にあるフレーム数。 これを0 (自動) から変更することはお勧めしません。"
110
+AMF.H264.WaitForTask="タスクの待機"
111
+AMF.H264.WaitForTask.Description="不明、実験的"
112
+AMF.H264.PreAnalysisPass="事前解析パス"
113
+AMF.H264.PreAnalysisPass.Description="不明、実験的"
114
+AMF.H264.VBAQ="VBAQ"
115
+AMF.H264.VBAQ.Description="不明、実験的"
116
+AMF.H264.GOPSize="GOP サイズ"
117
+AMF.H264.GOPSize.Description="不明、実験的"
118
+AMF.H264.GOPAlignment="GOP 配置"
119
+AMF.H264.GOPAlignment.Description="不明、実験的"
120
+AMF.H264.MaximumReferenceFrames="最大参照フレーム"
121
+AMF.H264.MaximumReferenceFrames.Description="不明、実験的"
122
+AMF.H264.SlicesPerFrame="フレームあたりのスライス"
123
+AMF.H264.SlicesPerFrame.Description="各スロットにいくつのI-フレームスライスを格納する必要があるか?\nゼロの値を指定するとエンコーダは高速で決定します。\nイントラ-リフレッシュのエンコードは高速再生とシークに使用されます。"
124
+AMF.H264.SliceMode="スライスモード"
125
+AMF.H264.SliceMode.Description="不明、実験的"
126
+AMF.H264.MaximumSliceSize="最大スライスサイズ"
127
+AMF.H264.MaximumSliceSize.Description="不明、実験的"
128
+AMF.H264.SliceControlMode="スライスコントロールモード"
129
+AMF.H264.SliceControlMode.Description="不明、実験的"
130
+AMF.H264.SliceControlSize="スライスコントロールサイズ"
131
+AMF.H264.SliceControlSize.Description="不明、実験的"
132
+AMF.H264.IntraRefresh.NumberOfStripes="イントラ-リフレッシュストライプ数"
133
+AMF.H264.IntraRefresh.NumberOfStripes.Description="不明、実験的"
134
+AMF.H264.IntraRefresh.MacroblocksPerSlot="スロットごとのマクロブロックのイントラ-リフレッシュ数"
135
+AMF.H264.IntraRefresh.MacroblocksPerSlot.Description="各スロットにいくつのマクロブロックを格納する必要があるか?\nゼロの値を指定するとこの機能は無効になります。\nイントラ-リフレッシュのエンコードは高速再生とシークに使用されます。"
136
+AMF.H264.VideoAPI="映像 API"
137
+AMF.H264.VideoAPI.Description="エンコードに使用する API。"
138
+AMF.H264.VideoAdapter="ビデオアダプター"
139
+AMF.H264.VideoAdapter.Description="エンコードに使用するアダプター。"
140
+AMF.H264.OpenCL="OpenCL"
141
+AMF.H264.OpenCL.Description="エンコーダはOpenCLを使用して個々のフレームを送信する必要がありますか?"
142
 AMF.H264.View="表示モード"
143
 AMF.H264.View.Description="どのプロパティが表示されるか。  'エキスパート' または 'マスター' の表示モードを使用する場合はサポートを受けられません。"
144
 AMF.H264.View.Basic="基本"
145
 AMF.H264.View.Advanced="詳細設定"
146
 AMF.H264.View.Expert="エキスパート"
147
 AMF.H264.View.Master="マスター"
148
-AMF.H264.UnlockProperties="プロパティのロック解除"
149
 AMF.H264.Debug="デバッグ"
150
 AMF.H264.Debug.Description="追加のデバッグログ出力を有効にし、これはこのエンコーダでサポートが必要なときにアクティブにする必要があります。"
151
-AMF.Util.Default="既定値"
152
-AMF.Util.Automatic="自動"
153
-AMF.Util.Manual="手動"
154
-AMF.Util.Toggle.Disabled="無効"
155
-AMF.Util.Toggle.Enabled="有効"
156
+
157
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/ko-KR.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/ko-KR.ini Changed
146
 
1
@@ -1,3 +1,8 @@
2
+AMF.Util.Default="기본값"
3
+AMF.Util.Automatic="자동"
4
+AMF.Util.Manual="수동"
5
+AMF.Util.Toggle.Disabled="비활성화"
6
+AMF.Util.Toggle.Enabled="활성화"
7
 AMF.H264.Preset="사전 설정"
8
 AMF.H264.Preset.ResetToDefaults="기본값으로 복구"
9
 AMF.H264.Preset.Recording="녹화"
10
@@ -20,12 +25,6 @@
11
 AMF.H264.Profile.Description="인코딩에 사용할 H.264 프로파일을 선택합니다:\n- 'Baseline'은 지원하는 플랫폼이 가장 많습니다,\n- 'Main'은 비교적 오래된 장치에서 지원합니다. (모바일 장치를 대상으로 한다면 추천하는 설정입니다),\n- 'High'는 현재 장치에서 지원하는 설정입니다 (추천)."
12
 AMF.H264.ProfileLevel="프로필 수준"
13
 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을 지원합니다."
14
-AMF.H264.MaximumLTRFrames="최대 장기참조 프레임"
15
-AMF.H264.MaximumLTRFrames.Description="장기참조 프레임(LTR)은 인코더가 특정 프레임을 참조 가능하게 만들어 줍니다.\n이 설정은 B-화면 기능이 지원되지 않거나 필요한 경우 품질을 올리는데 도움이 될 수 있습니다.\n장기참조 프레임은 B-화면과 동시에 사용할 수 없습니다."
16
-AMF.H264.ScanType="스캔 형식"
17
-AMF.H264.ScanType.Description="주사 방식을 설정합니다. 항상 '프로그레시브'로 두십시오."
18
-AMF.H264.ScanType.Progressive="프로그레시브"
19
-AMF.H264.ScanType.Interlaced="인터레이스"
20
 AMF.H264.RateControlMethod="속도 제어 방식"
21
 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의 지연시간과 부하가 허용한다면 목표 비트레이트에 가까운 수준을 유지하며, 그렇지 않은 상황에서는 그보다 높은 비트레이트를 사용합니다. (녹화에 추천)."
22
 AMF.H264.RateControlMethod.CQP="고정 QP (CQP)"
23
@@ -41,21 +40,17 @@
24
 AMF.H264.QP.Maximum="최대 QP"
25
 AMF.H264.QP.Maximum.Description="하나의 프레임에 사용하는 최고 QP (양자화 매개변수) 값"
26
 AMF.H264.QP.IFrame="I-프레임 QP"
27
-AMF.H264.QP.IFrame.Description="I-화면에 사용하는 고정 QP (양자화 매개변수) 값.\nI-화면 QP는 P-와 B-화면 QP값과 같거나 커야 함."
28
+AMF.H264.QP.IFrame.Description="I-화면에 사용할 고정 QP 값입니다."
29
 AMF.H264.QP.PFrame="P-프레임 QP"
30
-AMF.H264.QP.PFrame.Description="P-화면에 사용하는 고정 QP (양자화 매개변수) 값.\nP-화면 QP는 B-화면 QP값과 같거나 혹은 커야 함."
31
+AMF.H264.QP.PFrame.Description="P-화면에 사용할 고정 QP 값입니다."
32
 AMF.H264.QP.BFrame="BP-프레임 QP"
33
 AMF.H264.QP.BFrame.Description="B-화면에 사용하는 고정 QP (양자화 매개변수) 값."
34
-AMF.H264.QP.BPictureDelta="B-화면 델타 QP"
35
-AMF.H264.QP.BPictureDelta.Description="마지막 비참조 B-화면의 델타 QP."
36
-AMF.H264.QP.ReferenceBPictureDelta="참조 B-화면 델타 QP"
37
-AMF.H264.QP.ReferenceBPictureDelta.Description="마지막 참조 B-화면의 델타 QP."
38
 AMF.H264.VBVBuffer="VBV 버퍼"
39
 AMF.H264.VBVBuffer.Description="VBV 버퍼 크기를 결정하는 방식을 설정합니다:\n-'자동'은 엄격도의 제약하에 크기를 계산합니다.\n-'수동'은 사용자가 크기를 조절할 수 있도록 허용합니다.\n일부 특정 속도제어 방식이 사용하는 VBV (Video Buffering Verifier) 버퍼는 제공된 제약 안에서 전반적인 비트레이트를 유지합니다."
40
 AMF.H264.VBVBuffer.Strictness="VBV 버퍼 엄격도"
41
-AMF.H264.VBVBuffer.Strictness.Description="VBV 버퍼가 어떤 수준으로 제어될지 결정합니다. 100%에는 목표로 정한 비트레이트와 거의 일치하도록 조절하며 0%에서는 제약이 사라집니다."
42
+AMF.H264.VBVBuffer.Strictness.Description="VBV 버퍼의 엄격도를 설정합니다. 0%는 제약이 사라지고 100%는 최대한 제한을 합니다."
43
 AMF.H264.VBVBuffer.Size="VBV 버퍼 크기"
44
-AMF.H264.VBVBuffer.Size.Description="한 장면의 비트레이트 제어에 사용하는 VBV 버퍼의 크기를 설정합니다.\n크기를 작게 설정하면 거의 완벽하게 비트레이트 수준에 일치하는 결과를 얻지만, 작업을 하는데 더 많은 자원을 요구합니다."
45
+AMF.H264.VBVBuffer.Size.Description="VBV의 크기는 한 장면의 비트레이트 제어에 사용하는 단위입니다."
46
 AMF.H264.VBVBuffer.Fullness="VBV 버퍼 충만도"
47
 AMF.H264.VBVBuffer.Fullness.Description="초기 VBV버퍼가 얼마나 충만한지는 오로지 인코딩의 초반에만 영향을 미칩니다."
48
 AMF.H264.FillerData="채우기 정보"
49
@@ -64,46 +59,73 @@
50
 AMF.H264.FrameSkipping.Description="프레임 생략은 인코더가 목표로 하는 비트레이트 요건을 맞추기 위해 프레임을 떨어뜨릴 수 있습니다.\n인코더가 프레임 하나를 떨어뜨리면 마지막 프레임 NAL을 대신 전송합니다.\n목표 비트레이트가 아주 낮을 때 도움이 될 수 있습니다."
51
 AMF.H264.EnforceHRDCompatibility="HDR 호환모드 적용"
52
 AMF.H264.EnforceHRDCompatibility.Description="이론적 기본 디코더 강제는 프레임 하나의 최대 QP값 변화를 제한하는 설정입니다.\n녹화나 방송에는 적합하지 않고 기본 소프트웨어 디코더만 사용 가능한 매우 낡은 장치에서 영상을 재생할 때 사용합니다."
53
-AMF.H264.MaximumAccessUnitSize="최대 접근 유닛 크기"
54
-AMF.H264.MaximumAccessUnitSize.Description="NAL 장치에서 단일 접근 유닛의 가장 큰 크기를 결정합니다. 0 값은 인코더가 최적화된 수치를 결정하도록 허용합니다."
55
 AMF.H264.KeyframeInterval="키프레임 간격"
56
 AMF.H264.KeyframeInterval.Description="손실이 불가능한 프레임 사이에 얼마나 많은 시간(초)이 필요한지 설정합니다.\n또한 영상(GOP) 크기도 제어합니다."
57
 AMF.H264.IDRPeriod="IDR 주기"
58
 AMF.H264.IDRPeriod.Description="프레임 내에서 순간 복호 갱신(nstantaneous Decoding Refreshes) 사이의 거리를 설정합니다. 또한, GOP-장면 크기를 제어합니다."
59
-AMF.H264.HeaderInsertionSpacing="헤더 삽입 간격"
60
-AMF.H264.HeaderInsertionSpacing.Description="NAL 헤더 사이에 얼마나 많은 프레임이 필요한지 설정합니다. 0(자동)에서 바꾸는 것은 추천하지 않습니다."
61
-AMF.H264.BPicture.Pattern="B-화면 양식"
62
-AMF.H264.BPicture.Pattern.Description="인코딩에서 얼마나 많은 B-화면이 필요한지 결정합니다. 수치가 늘어날수록 품질은 올라가고 필요한 성능은 높아집니다.\n2세대와 3 세대 VCE 카드에서만 지원이 됩니다."
63
-AMF.H264.BPicture.Reference="B-화면 참조"
64
-AMF.H264.BPicture.Reference.Description="다른 B-화면뿐만 아니라 P-/I-화면에도 B-화면을 참조할 수 있도록 허용합니다.\n높은 성능이 요구되지만 품질 개선에는 그리 큰 효과가 없습니다."
65
+AMF.H264.BFrame.Pattern.Description="인코딩에 얼마나 많은 B-화면을 사용할지 설정합니다.\n2, 3세대 VCE카드에서 지원합니다. 인코딩 성능에 부정적인 영향을 줍니다."
66
+AMF.H264.BFrame.DeltaQP="B-화면 델타 QP"
67
+AMF.H264.BFrame.DeltaQP.Description="비참조 B-화면에 쓰이는 마지막 I- 혹은P-화면의 델타 QP 값"
68
+AMF.H264.BFrame.Reference="참조가능한 B-화면"
69
+AMF.H264.BFrame.Reference.Description="P-와 I-화면뿐만 아니라 B-화면도 참조할 수 있도록 허용합니다."
70
+AMF.H264.BFrame.ReferenceDeltaQP="참조가능한 B-화면 델타 QP"
71
+AMF.H264.BFrame.ReferenceDeltaQP.Description="비참조 B-화면에 쓰이는 마지막 I- 혹은P-화면의 델타 QP 값."
72
 AMF.H264.DeblockingFilter="디블록 필터"
73
 AMF.H264.DeblockingFilter.Description="디코더가 인코딩된 작업에 디블록 필터를 사용할 수 있도록 허용합니다."
74
-AMF.H264.SlicesPerFrame="조각 당 프레임"
75
-AMF.H264.SlicesPerFrame.Description="프레임마다 얼마나 많은 I-화면 조각을 저장할지 결정합니다.\n0값은 인코더가 상태에 따라 맞춰 조절합니다.\n인트라-리프레시 인코딩은 더 빠른 재생과 탐색을 위해 사용합니다."
76
-AMF.H264.IntraRefreshNumMBsPerSlot="슬롯 당 매크로블록의 인트라-리프레시 수"
77
-AMF.H264.IntraRefreshNumMBsPerSlot.Description="슬롯마다 얼마나 많은 매크로 블록을 저장할지 결정합니다.\n\0값은 인코더가 상태에 따라 맞춰 조절합니다.\n인인트라-리프레시 인코딩은 더 빠른 재생과 탐색을 위해 사용합니다."
78
+AMF.H264.ScanType="스캔 형식"
79
+AMF.H264.ScanType.Description="주사 방식을 설정합니다. 항상 '프로그레시브'로 두십시오."
80
+AMF.H264.ScanType.Progressive="프로그레시브"
81
+AMF.H264.ScanType.Interlaced="인터레이스"
82
 AMF.H264.MotionEstimation="동작 예측"
83
 AMF.H264.MotionEstimation.Description="동작 추정은 픽셀의 움직임을 추정하여 필요한 비트레이트를 줄일 수 있게 합니다."
84
 AMF.H264.MotionEstimation.None="없음"
85
 AMF.H264.MotionEstimation.Half="1/2 화소"
86
 AMF.H264.MotionEstimation.Quarter="1/4 화소"
87
 AMF.H264.MotionEstimation.Both="1/2 & 1/4 화소"
88
-AMF.H264.Device="장치"
89
-AMF.H264.Device.Description="인코덩에 사용할 장치를 설정합니다.\n메모리 형식에서 'Host'를 선택하면 안됩니다."
90
-AMF.H264.UseOpenCL="OpenCL 사용"
91
-AMF.H264.UseOpenCL.Description="해당 인코더가 개별 프레임을 제출할 때 OpenCL을 사용하겠습니까?"
92
+AMF.H264.CodingType="부호화 형식"
93
+AMF.H264.CodingType.Description="부호화 형식을 결정합니다:\n* \@AMF.Util.Default\@ 은 AMF가 자동으로 선택합니다 (추천).\n* CALVC (문맥기반 적응적 가변길이 부호화) 는 빠르지만, 더 큽니다.\n* CABAC (문맥기반 적응적 이진산술 부호화) 는 느리지만, 더 작습니다."
94
+AMF.H264.MaximumLTRFrames="최대 장기참조 프레임"
95
+AMF.H264.MaximumLTRFrames.Description="장기참조 프레임(LTR)은 인코더가 긴 시계에서 특정 프레임을 참조 가능하게 만들어 줍니다.\n장기참조 프레임은 B-화면과 동시에 사용할 수 없습니다."
96
+AMF.H264.MaximumAccessUnitSize="최대 접근 유닛 크기"
97
+AMF.H264.MaximumAccessUnitSize.Description="NAL 장치에서 단일 접근 유닛의 가장 큰 크기를 결정합니다. 0 값은 인코더가 최적화된 수치를 결정하도록 허용합니다."
98
+AMF.H264.HeaderInsertionSpacing="헤더 삽입 간격"
99
+AMF.H264.HeaderInsertionSpacing.Description="NAL 헤더 사이에 얼마나 많은 프레임이 필요한지 설정합니다. 0(자동)에서 바꾸는 것은 추천하지 않습니다."
100
+AMF.H264.WaitForTask="작업을 대기"
101
+AMF.H264.WaitForTask.Description="알수 없음, 실험적인 기능"
102
+AMF.H264.VBAQ="VBAQ"
103
+AMF.H264.VBAQ.Description="알수 없음, 실험적인 기능"
104
+AMF.H264.GOPSize="GOP 크기"
105
+AMF.H264.GOPSize.Description="알수 없음, 실험적인 기능"
106
+AMF.H264.GOPAlignment="GOP 조정"
107
+AMF.H264.GOPAlignment.Description="알수 없음, 실험적인 기능"
108
+AMF.H264.MaximumReferenceFrames="최대 참조 프레임"
109
+AMF.H264.MaximumReferenceFrames.Description="알수 없음, 실험적인 기능"
110
+AMF.H264.SlicesPerFrame="조각 당 프레임"
111
+AMF.H264.SlicesPerFrame.Description="프레임마다 얼마나 많은 I-화면 조각을 저장할지 결정합니다.\n0값은 인코더가 상태에 따라 맞춰 조절합니다.\n인트라-리프레시 인코딩은 더 빠른 재생과 탐색을 위해 사용합니다."
112
+AMF.H264.SliceMode="분할 모드"
113
+AMF.H264.SliceMode.Description="알수 없음, 실험적인 기능"
114
+AMF.H264.MaximumSliceSize="최대 분할 크기"
115
+AMF.H264.MaximumSliceSize.Description="알수 없음, 실험적인 기능"
116
+AMF.H264.SliceControlMode="분할 제어 모드"
117
+AMF.H264.SliceControlMode.Description="알수 없음, 실험적인 기능"
118
+AMF.H264.SliceControlSize="분할 제어 크기"
119
+AMF.H264.SliceControlSize.Description="알수 없음, 실험적인 기능"
120
+AMF.H264.IntraRefresh.NumberOfStripes="인트라-리프레시 줄무늬 개수"
121
+AMF.H264.IntraRefresh.NumberOfStripes.Description="알수 없음, 실험적인 기능"
122
+AMF.H264.IntraRefresh.MacroblocksPerSlot="슬롯 당 매크로블록의 인트라-리프레시 수"
123
+AMF.H264.IntraRefresh.MacroblocksPerSlot.Description="슬롯마다 얼마나 많은 매크로 블록을 저장할지 결정합니다.\n\0값은 인코더가 상태에 따라 맞춰 조절합니다.\n인트라-리프레시 인코딩은 더 빠른 재생과 탐색을 위해 사용합니다."
124
+AMF.H264.VideoAPI="비디오 API"
125
+AMF.H264.VideoAPI.Description="인코딩에 어떤 API를 사용할지 설정합니다."
126
+AMF.H264.VideoAdapter="비디오 어댑터:"
127
+AMF.H264.VideoAdapter.Description="인코딩에 어떤 어댑터를 사용할지 설정합니다."
128
+AMF.H264.OpenCL="OpenCL"
129
+AMF.H264.OpenCL.Description="해당 인코더가 개별 프레임을 제출할 때 OpenCL을 사용하겠습니까?"
130
 AMF.H264.View="보기 모드"
131
 AMF.H264.View.Description="어떤 설정을 표시할지 결정합니다. '숙련' 혹은 '달인' 표시 모드에서는 지원을 받을 수 없습니다."
132
 AMF.H264.View.Basic="기본"
133
 AMF.H264.View.Advanced="고급"
134
 AMF.H264.View.Expert="숙련"
135
 AMF.H264.View.Master="달인"
136
-AMF.H264.UnlockProperties="속성 잠금해제"
137
-AMF.H264.UnlockProperties.Description="특정 설정을 부분적이 아닌 전체 범위를 다룰 수 있도록 잠금을 해제합니다."
138
 AMF.H264.Debug="디버그"
139
 AMF.H264.Debug.Description="추가적인 디버그 기록을 활성화하여 이 인코더에 대한 지원이 필요할 때 제출하십시오."
140
-AMF.Util.Default="기본값"
141
-AMF.Util.Automatic="자동"
142
-AMF.Util.Manual="수동"
143
-AMF.Util.Toggle.Disabled="비활성화"
144
-AMF.Util.Toggle.Enabled="활성화"
145
+
146
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/nb-NO.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/nb-NO.ini Changed
25
 
1
@@ -1,3 +1,7 @@
2
+AMF.Util.Default="Standard"
3
+AMF.Util.Automatic="Automatisk"
4
+AMF.Util.Toggle.Disabled="Deaktivert"
5
+AMF.Util.Toggle.Enabled="Aktivert"
6
 AMF.H264.Usage.Transcoding="Transkoding"
7
 AMF.H264.Usage.UltraLowLatency="Ultra-lav latens"
8
 AMF.H264.Usage.LowLatency="Lav latens"
9
@@ -7,13 +11,10 @@
10
 AMF.H264.QualityPreset.Quality="Kvalitet"
11
 AMF.H264.Profile="Profil"
12
 AMF.H264.ProfileLevel="Profilnivå"
13
-AMF.H264.ScanType="Skanne Type"
14
 AMF.H264.Bitrate.Target="Mål Bitrate"
15
 AMF.H264.Bitrate.Peak="Maks bitrate"
16
 AMF.H264.QP.Minimum="Minste QP"
17
 AMF.H264.QP.Maximum="Maksimal QP"
18
 AMF.H264.EnforceHRDCompatibility="Håndheve HRD kompatibilitet"
19
-AMF.Util.Default="Standard"
20
-AMF.Util.Automatic="Automatisk"
21
-AMF.Util.Toggle.Disabled="Deaktivert"
22
-AMF.Util.Toggle.Enabled="Aktivert"
23
+AMF.H264.ScanType="Skanne Type"
24
+
25
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/nl-NL.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/nl-NL.ini Changed
45
 
1
@@ -1,3 +1,7 @@
2
+AMF.Util.Default="Standaard"
3
+AMF.Util.Automatic="Automatisch"
4
+AMF.Util.Toggle.Disabled="Uitgeschakeld"
5
+AMF.Util.Toggle.Enabled="Ingeschakeld"
6
 AMF.H264.Preset="Voorkeursinstelling"
7
 AMF.H264.Preset.Recording="Opname"
8
 AMF.H264.Preset.HighQuality="Hoge kwaliteit"
9
@@ -17,11 +21,6 @@
10
 AMF.H264.Profile="Profiel"
11
 AMF.H264.ProfileLevel="Profielniveau"
12
 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"
13
-AMF.H264.MaximumLTRFrames="Maximale LTR Frames"
14
-AMF.H264.MaximumLTRFrames.Description="Long Term Reference (LTR) Frames zijn een functie waarmee de encoder bepaalde frames achter elkaar als refereerbaar kan markern.\nDit kan een positief effect hebben op de kwaliteit wanneer B-Pictures niet ondersteund of gewild zijn.\nLTR Frames kunnen niet samen met B-Pictures gebruikt worden en deencoder zal B-Pictures uitschakelen als deze worden gebruikt."
15
-AMF.H264.ScanType="Scantype"
16
-AMF.H264.ScanType.Progressive="Progressive"
17
-AMF.H264.ScanType.Interlaced="Interlaced"
18
 AMF.H264.RateControlMethod="Rate control methode"
19
 AMF.H264.RateControlMethod.CQP="Constant QP (CQP)"
20
 AMF.H264.RateControlMethod.CBR="Constant Bitrate (CBR)"
21
@@ -34,18 +33,13 @@
22
 AMF.H264.QP.IFrame="I-Frame QP"
23
 AMF.H264.QP.PFrame="P-Frame QP"
24
 AMF.H264.QP.BFrame="B-Frame QP"
25
-AMF.H264.QP.BPictureDelta="B-Picture Delta QP"
26
-AMF.H264.QP.BPictureDelta.Description="Delta QP (Quantization Parameter) waarde tot de laatste niet-reference B-Picture."
27
-AMF.H264.QP.ReferenceBPictureDelta="Referentie B-Picture Delta QP"
28
-AMF.H264.QP.ReferenceBPictureDelta.Description="Delta QP (Quantization Parameter) waarde tot de laatste referentie B-Picture,."
29
 AMF.H264.VBVBuffer="VBV Buffer"
30
 AMF.H264.FillerData="Opvuldata"
31
 AMF.H264.FrameSkipping="Frames overslaan"
32
 AMF.H264.EnforceHRDCompatibility="Forceer HDR compatibiliteit"
33
-AMF.H264.BPicture.Pattern="B-Picture patroon"
34
-AMF.H264.BPicture.Reference="B-Picture referentie"
35
 AMF.H264.DeblockingFilter="Deblocking Filter"
36
-AMF.Util.Default="Standaard"
37
-AMF.Util.Automatic="Automatisch"
38
-AMF.Util.Toggle.Disabled="Uitgeschakeld"
39
-AMF.Util.Toggle.Enabled="Ingeschakeld"
40
+AMF.H264.ScanType="Scantype"
41
+AMF.H264.ScanType.Progressive="Progressive"
42
+AMF.H264.ScanType.Interlaced="Interlaced"
43
+AMF.H264.MaximumLTRFrames="Maximale LTR Frames"
44
+
45
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/pl-PL.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/pl-PL.ini Changed
85
 
1
@@ -1,4 +1,10 @@
2
+AMF.Util.Default="Domyślne"
3
+AMF.Util.Automatic="Automatycznie"
4
+AMF.Util.Manual="Ustawienia własne"
5
+AMF.Util.Toggle.Disabled="Wyłączone"
6
+AMF.Util.Toggle.Enabled="Włączone"
7
 AMF.H264.Preset="Profil"
8
+AMF.H264.Preset.ResetToDefaults="Przywróć ustawienia domyślne"
9
 AMF.H264.Preset.Recording="Nagrywanie"
10
 AMF.H264.Preset.HighQuality="Wysoka jakość"
11
 AMF.H264.Preset.Indistinguishable="Nie do odróżnienia"
12
@@ -15,30 +21,61 @@
13
 AMF.H264.QualityPreset.Quality="Jakość"
14
 AMF.H264.Profile="Profil"
15
 AMF.H264.ProfileLevel="Profil"
16
-AMF.H264.ScanType="Metoda skanowania"
17
-AMF.H264.ScanType.Progressive="Progresywne"
18
-AMF.H264.ScanType.Interlaced="Z przeplotem"
19
 AMF.H264.RateControlMethod="Metoda kontroli przepływności"
20
 AMF.H264.RateControlMethod.CQP="Stała QP (CQP)"
21
 AMF.H264.RateControlMethod.CBR="Stała przepływność (CBR)"
22
 AMF.H264.RateControlMethod.VBR.Peak="Zmienna przepływność (z ograniczeniem górnym) (VBR)"
23
 AMF.H264.RateControlMethod.VBR.Latency="Zmienna przepływność (z ograniczeniem opóźnieniem) (VBR_LAT)"
24
 AMF.H264.Bitrate.Target="Przepływność docelowa"
25
+AMF.H264.Bitrate.Target.Description="Średni bitrate do uzyskania w sekwencji."
26
 AMF.H264.Bitrate.Peak="Przepływność szczytowa"
27
+AMF.H264.Bitrate.Peak.Description="Maksymalny bitrate do uzyskania w sekwencji."
28
 AMF.H264.QP.Minimum="Minimalna QP"
29
+AMF.H264.QP.Minimum.Description="Najniższa wartość QP (parametr kwantyzacji) do użycia w ramce."
30
 AMF.H264.QP.Maximum="Maksymalna QP"
31
+AMF.H264.QP.Maximum.Description="Najwyższa wartość QP (parametr kwantyzacji) do użycia w ramce."
32
 AMF.H264.QP.IFrame="I-Frame QP"
33
+AMF.H264.QP.IFrame.Description="Stała wartość QP dla ramek I-Frame."
34
 AMF.H264.QP.PFrame="P-Frame QP"
35
+AMF.H264.QP.PFrame.Description="Stała wartość QP dla ramek P-Frame."
36
 AMF.H264.QP.BFrame="B-Frame QP"
37
-AMF.H264.QP.BPictureDelta="B-Picture Delta QP"
38
-AMF.H264.QP.ReferenceBPictureDelta="Referencyjne B-Picture Delta QP"
39
+AMF.H264.QP.BFrame.Description="Stała wartość QP (parametr kwantyzacji) do użycia w ramce B-Frame."
40
+AMF.H264.VBVBuffer="Bufor VBV"
41
+AMF.H264.VBVBuffer.Strictness="Odchylenie bufora VBV"
42
+AMF.H264.VBVBuffer.Strictness.Description="Określa rygor wykorzystania bufora VBV, gdzie 100% oznacza pełne podporządkowanie wartości a 0% - dowolne."
43
+AMF.H264.VBVBuffer.Size="Rozmiar bufora VBV"
44
+AMF.H264.VBVBuffer.Size.Description="Rozmiar bufora VBV używanego w kontroli przepływności sekwencji kodowania."
45
+AMF.H264.VBVBuffer.Fullness="Zapełnienie bufora VBV"
46
+AMF.H264.VBVBuffer.Fullness.Description="Jak bardzo zapełniony na starcie powinien być bufor VBV. Wpływa jedynie na początkową sekwencję kodowania."
47
 AMF.H264.FillerData="Filler Data"
48
 AMF.H264.FrameSkipping="Pomijanie klatek"
49
 AMF.H264.EnforceHRDCompatibility="Wymuszanie zgodności HRD"
50
-AMF.H264.BPicture.Pattern="Schemat B-Picture"
51
-AMF.H264.BPicture.Reference="Referencyjny B-Picture"
52
+AMF.H264.KeyframeInterval="Interwał klatki kluczowej"
53
+AMF.H264.KeyframeInterval.Description="Określa odległość (w sekundach) między klatkami kluczowymi oraz kontroluje rozmiar GOP."
54
+AMF.H264.IDRPeriod="Okres IDR"
55
+AMF.H264.IDRPeriod.Description="Określa (w klatkach) odległość między natychmiastowymi odświeżeniami dekodera. Kontroluje również rozmiar sekwencji GOP.
56
+"
57
 AMF.H264.DeblockingFilter="Filtr niwelujacy bloki obrazu"
58
-AMF.Util.Default="Domyślne"
59
-AMF.Util.Automatic="Automatycznie"
60
-AMF.Util.Toggle.Disabled="Wyłączone"
61
-AMF.Util.Toggle.Enabled="Włączone"
62
+AMF.H264.ScanType="Metoda skanowania"
63
+AMF.H264.ScanType.Progressive="Progresywne"
64
+AMF.H264.ScanType.Interlaced="Z przeplotem"
65
+AMF.H264.CodingType="Typ kodowania"
66
+AMF.H264.MaximumAccessUnitSize="Maksymalny rozmiar Access Unit"
67
+AMF.H264.MaximumAccessUnitSize.Description="Maksymalny rozmiar Access Unit. Wartość 0 umożliwia enkoderowi wybranie najlepszej wartości."
68
+AMF.H264.HeaderInsertionSpacing="Rozmiar nagłówka (w klatkach)"
69
+AMF.H264.HeaderInsertionSpacing.Description="Ile klatek powinno być między nagłówkami. Nie zaleca się zmieniać wartości na inną niż 0 (automatycznie)."
70
+AMF.H264.VideoAPI="Typ API"
71
+AMF.H264.VideoAPI.Description="Rodzaj API wykorzystywanego do enkodowania."
72
+AMF.H264.VideoAdapter="Karta graficzna"
73
+AMF.H264.VideoAdapter.Description="Karta graficzna wykorzystywana do enkodowania."
74
+AMF.H264.OpenCL="OpenCL"
75
+AMF.H264.OpenCL.Description="Czy enkoder ma użyć OpenCL do wysyłania poszczególnych klatek?"
76
+AMF.H264.View="Tryb ustawień"
77
+AMF.H264.View.Description="Którego typu ustawień używać.\nWłączenie '\@AMF.H264.View.Master\@' oznacza rezygnację ze wsparcia technicznego."
78
+AMF.H264.View.Basic="Podstawowy"
79
+AMF.H264.View.Advanced="Zaawansowany"
80
+AMF.H264.View.Expert="Ekspercki"
81
+AMF.H264.View.Master="Pełny"
82
+AMF.H264.Debug="Debugowanie"
83
+AMF.H264.Debug.Description="Włącza dodatkowe opcje logowania w trybie debug. Przydatne w przypadku poszukiwania wsparcia technicznego dla tego enkodera."
84
+
85
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/ru-RU.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/ru-RU.ini Changed
101
 
1
@@ -1,3 +1,8 @@
2
+AMF.Util.Default="По умолчанию"
3
+AMF.Util.Automatic="Автоматически"
4
+AMF.Util.Manual="Руководство"
5
+AMF.Util.Toggle.Disabled="Выключено"
6
+AMF.Util.Toggle.Enabled="Включено"
7
 AMF.H264.Preset="Предустановка"
8
 AMF.H264.Preset.ResetToDefaults="Сброс по умолчанию"
9
 AMF.H264.Preset.Recording="Запись"
10
@@ -19,12 +24,6 @@
11
 AMF.H264.Profile="Профиль кодирования"
12
 AMF.H264.ProfileLevel="Уровень профиля"
13
 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"
14
-AMF.H264.MaximumLTRFrames="Максимум LTR-кадров"
15
-AMF.H264.MaximumLTRFrames.Description="Long Term Reference (LTR) Frames - функция позволяющая кодировщику помечать определенные кадры в последовательности как ссылаемые.\nЭта функция может поднять качество, если функция B-Pictrues не поддерживается или не желательна.\nФункция LTR Frames не может использоваться вместе с функцией B-Pictrues и кодировщик отключит функцию B-Pictrues если таковая используется."
16
-AMF.H264.ScanType="Развертка"
17
-AMF.H264.ScanType.Description="Какой режим сканирования использовать; всегда оставляется этот параметр на 'прогрессивном'."
18
-AMF.H264.ScanType.Progressive="Прогрессивная"
19
-AMF.H264.ScanType.Interlaced="Чересстрочная"
20
 AMF.H264.RateControlMethod="Метод кодирования"
21
 AMF.H264.RateControlMethod.CQP="CQP: постоянное качество"
22
 AMF.H264.RateControlMethod.CBR="CBR: постоянный битрейт"
23
@@ -39,65 +38,47 @@
24
 AMF.H264.QP.Maximum="Максимальное QP"
25
 AMF.H264.QP.Maximum.Description="Наибольшее значение QP (Параметр квантования) для использования в кадре."
26
 AMF.H264.QP.IFrame="I-кадр QP"
27
-AMF.H264.QP.IFrame.Description="Фиксированное значение QP (Параметр квантования) для использования в I-Кадрах.\nQP I-Кадров должен быть равен или больше чем QP P- и B-Кадров."
28
 AMF.H264.QP.PFrame="P-кадр QP"
29
-AMF.H264.QP.PFrame.Description="Фиксированное значение QP (Параметр квантования) для использования в P-Кадрах.\nQP P-Кадров должен быть равен или больше чем QP B-Кадров."
30
 AMF.H264.QP.BFrame="B-кадр QP"
31
 AMF.H264.QP.BFrame.Description="Фиксированное значение QP (Параметр квантования) для использования в B-Кадрах."
32
-AMF.H264.QP.BPictureDelta="B-кадры дельта QP"
33
-AMF.H264.QP.BPictureDelta.Description="Дельта QP до последнего не референсного B-кадра."
34
-AMF.H264.QP.ReferenceBPictureDelta="Референсные B-кадры дельта QP"
35
-AMF.H264.QP.ReferenceBPictureDelta.Description="Дельта QP до последнего референсного B-кадра."
36
 AMF.H264.VBVBuffer="Буфер VBV"
37
 AMF.H264.VBVBuffer.Description="Какой метод следует использовать для определения Размера буфера VBV:\n- '\@AMF.Util.Automatic\@' рассчитывает размер ограничивающийся строгостью,\n- '\@AMF.Util.Manual\@' позволяет пользователю контролировать размер буфера.\nVBV (Верификатор буферизации видео) буфер используется некоторыми Методами управления скоростью, чтобы сохранить общий битрейт в пределах заданных ограничений."
38
 AMF.H264.VBVBuffer.Strictness="Строгость буфера VBV"
39
-AMF.H264.VBVBuffer.Strictness.Description="Насколько строго должен быть ограничен буфер VBV: 100% — почти полное соответствие целевому битрейту, 0% — без ограничений."
40
 AMF.H264.VBVBuffer.Size="Размер буфера VBV"
41
 AMF.H264.VBVBuffer.Fullness="Заполнение буфера VBV"
42
 AMF.H264.VBVBuffer.Fullness.Description="Изначальная степень заполнения VBV буфера, будет влиять только на первоначальную последовательность кодирования."
43
 AMF.H264.FillerData="Данные наполнителя"
44
 AMF.H264.FrameSkipping="Пропуск кадров"
45
 AMF.H264.EnforceHRDCompatibility="Принудительная HRD совместимость"
46
-AMF.H264.MaximumAccessUnitSize="Максимальный Размер Блока Доступа"
47
-AMF.H264.MaximumAccessUnitSize.Description="Большой размер блока доступа для NAL. Значение 0 позволяет регулировать, чтобы выбрать лучший."
48
 AMF.H264.KeyframeInterval="Интервал ключевых кадров"
49
 AMF.H264.KeyframeInterval.Description="Сколько секунд должен быть просадок кадров.\nТакже контролирует GOP Size."
50
 AMF.H264.IDRPeriod="Период IDR"
51
 AMF.H264.IDRPeriod.Description="Определяет расстояние между Мгновенными обновлениями декодирования (IDR) в кадрах. Так же контролирует размер последовательности GOP."
52
-AMF.H264.HeaderInsertionSpacing="Расстояние вставки заголовка"
53
-AMF.H264.HeaderInsertionSpacing.Description="Сколько кадров должно быть между заголовками NAL. Не рекомендуется менять значение с 0 (автоматически)."
54
-AMF.H264.BPicture.Pattern="Патерн B-кадра"
55
-AMF.H264.BPicture.Pattern.Description="Сколько кадров B-Pictures должно быть разрешено для кодирования. Имеет положительный эффект на качестве и негативный на производительности.\nПоддерживает только второе поколение VCE. Значение функции LTR Frames должно быть равно нулю."
56
-AMF.H264.BPicture.Reference="Референс B-кадра"
57
-AMF.H264.BPicture.Reference.Description="Разрешает B-Кадрам ссылаться на другие B-Кадры как и на P- и I-Кадры.\nОгромный урон производительности, исправление низкого качества."
58
 AMF.H264.DeblockingFilter="Фильтр деблокинга"
59
 AMF.H264.DeblockingFilter.Description="Устанавливает флаг, что декодер может использовать фильтр удаления блочности для прямой трансляции."
60
-AMF.H264.SlicesPerFrame="Количество частей на кадр"
61
-AMF.H264.SlicesPerFrame.Description="Сколько кусков I-Кадров должно быть сохранено в каждом кадре?\nЗначение 0 позволяет кодировщику выбирать \"на лету\".\nКодирование Intra-Refresh используется для быстрого воспроизведения и поиска при перемотке."
62
-AMF.H264.IntraRefreshNumMBsPerSlot="Интра-обновить Количество Макроблоков в слот"
63
-AMF.H264.IntraRefreshNumMBsPerSlot.Description="Сколько Макроблоков должно быть сохранено в каждом слоте?\nЗначение 0 позволяет кодировщику выбирать \"на лету\".\nКодирование Intra-Refresh используется для быстрого воспроизведения и поиска при перемотке."
64
+AMF.H264.ScanType="Развертка"
65
+AMF.H264.ScanType.Description="Какой режим сканирования использовать; всегда оставляется этот параметр на 'прогрессивном'."
66
+AMF.H264.ScanType.Progressive="Прогрессивная"
67
+AMF.H264.ScanType.Interlaced="Чересстрочная"
68
 AMF.H264.MotionEstimation="Оценка движения"
69
 AMF.H264.MotionEstimation.Description="Оценки движения позволяет кодировщику необходимость уменьшить Битрейт, оценивая, где пиксель прошел."
70
 AMF.H264.MotionEstimation.None="Нет"
71
 AMF.H264.MotionEstimation.Half="Пол-пиксельная"
72
 AMF.H264.MotionEstimation.Quarter="Четверть-пиксельная"
73
 AMF.H264.MotionEstimation.Both="Пол- & Четверть-пиксельная"
74
-AMF.H264.Device="Устройство"
75
-AMF.H264.Device.Description="Которое из устройств использовать для кодирования.\nТип памяти должен быть не 'Host'."
76
-AMF.H264.UseOpenCL="Использовать OpenCL"
77
-AMF.H264.UseOpenCL.Description="Должен ли кодировщик использовать OpenCL для подтверждения индивидуальных кадров?"
78
+AMF.H264.MaximumLTRFrames="Максимум LTR-кадров"
79
+AMF.H264.MaximumAccessUnitSize="Максимальный Размер Блока Доступа"
80
+AMF.H264.MaximumAccessUnitSize.Description="Большой размер блока доступа для NAL. Значение 0 позволяет регулировать, чтобы выбрать лучший."
81
+AMF.H264.HeaderInsertionSpacing="Расстояние вставки заголовка"
82
+AMF.H264.HeaderInsertionSpacing.Description="Сколько кадров должно быть между заголовками NAL. Не рекомендуется менять значение с 0 (автоматически)."
83
+AMF.H264.SlicesPerFrame="Количество частей на кадр"
84
+AMF.H264.SlicesPerFrame.Description="Сколько кусков I-Кадров должно быть сохранено в каждом кадре?\nЗначение 0 позволяет кодировщику выбирать \"на лету\".\nКодирование Intra-Refresh используется для быстрого воспроизведения и поиска при перемотке."
85
 AMF.H264.View="Режим просмотра"
86
 AMF.H264.View.Description="Какие параметры должны быть видны. Вы не будете получать поддержку при использовании режимов 'Эксперт' и 'Мастер'."
87
 AMF.H264.View.Basic="Обычный"
88
 AMF.H264.View.Advanced="Расширенный"
89
 AMF.H264.View.Expert="Эксперт"
90
 AMF.H264.View.Master="Мастер"
91
-AMF.H264.UnlockProperties="Разблокировать параметры"
92
-AMF.H264.UnlockProperties.Description="Разблокировать определённые параметры до их полного, неограниченного диапазона."
93
 AMF.H264.Debug="Отладка"
94
 AMF.H264.Debug.Description="Включить дополнительные логи для отладки; следует включить, если вам нужна поддержка с этим кодировщиком."
95
-AMF.Util.Default="По умолчанию"
96
-AMF.Util.Automatic="Автоматически"
97
-AMF.Util.Manual="Руководство"
98
-AMF.Util.Toggle.Disabled="Выключено"
99
-AMF.Util.Toggle.Enabled="Включено"
100
+
101
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/sk-SK.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/sk-SK.ini Changed
6
 
1
@@ -4,3 +4,4 @@
2
 AMF.H264.Preset.Twitch="Twitch"
3
 AMF.H264.Preset.YouTube="YouTube"
4
 AMF.H264.Profile="Profil"
5
+
6
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/sr-CS.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/sr-CS.ini Changed
56
 
1
@@ -1,23 +1,29 @@
2
+AMF.Util.Default="Podrazumevano"
3
+AMF.Util.Automatic="Automatski"
4
+AMF.Util.Manual="Ručno"
5
+AMF.Util.Toggle.Disabled="Onemogućeno"
6
+AMF.Util.Toggle.Enabled="Omogućeno"
7
 AMF.H264.Preset="Šablon"
8
+AMF.H264.Preset.ResetToDefaults="Vrati na podrazumevane vrednosti"
9
 AMF.H264.Preset.Recording="Snimanje"
10
 AMF.H264.Preset.HighQuality="Visoki kvalitet"
11
 AMF.H264.Preset.Indistinguishable="Istovetno"
12
 AMF.H264.Preset.Lossless="Bez gubitaka"
13
 AMF.H264.Preset.Twitch="Twitch"
14
 AMF.H264.Preset.YouTube="YouTube"
15
+AMF.H264.Usage="Upotreba"
16
+AMF.H264.Usage.Description="Za koju upotrebu bi AMF trebao biti podešen:\n- '\@AMF.H264.Usage.Transcoding\@' je transkoding opšte namene (preporučeno),\n- '\@AMF.H264.Usage.UltraLowLatency\@' je za enkoding veoma niskog kašnjenja,\n- '\@AMF.H264.Usage.LowLatency\@' je slično prethodnom sa malo višim kašnjenjem.\nEmitovanje podržava samo '\@AMF.H264.Usage.Transcoding\@', sve ostale vrednosti se mogu koristiti za snimanje."
17
 AMF.H264.Usage.Transcoding="Transkodiranje"
18
 AMF.H264.Usage.UltraLowLatency="Ultra nisko kašnjenje"
19
 AMF.H264.Usage.LowLatency="Nisko kašnjenje"
20
 AMF.H264.QualityPreset="Šablon kvaliteta"
21
+AMF.H264.QualityPreset.Description="Koji šablon za kvalitet bi AMF trebao da cilja:\n- '\@AMF.H264.QualityPreset.Speed\@' je najbrži sa najlošijim kvalitetom,\n- '\@AMF.H264.QualityPreset.Balanced\@' je balansiran spoj oba,\n- '\@AMF.H264.QualityPreset.Quality\@' daje najbolji kvalitet za zadati bitrejt."
22
 AMF.H264.QualityPreset.Speed="Brzina"
23
 AMF.H264.QualityPreset.Balanced="Izbalansirano"
24
 AMF.H264.QualityPreset.Quality="Kvalitet"
25
 AMF.H264.Profile="Profil"
26
+AMF.H264.Profile.Description="Koji H.264 profil koristiti za enkodiranje:\n- 'Baseline' ima najveću podršku platformi,\n- 'Main' je podržan na starijim uređajima (preporučeno ako se ide ka mobilnim uređajima),\n- 'High' je podržan na aktuelnim uređajima (preporučeno)."
27
 AMF.H264.ProfileLevel="Nivo profila"
28
-AMF.H264.MaximumLTRFrames="Maksimalan broj LTR frejmova"
29
-AMF.H264.ScanType="Vrsta skeniranja"
30
-AMF.H264.ScanType.Progressive="Progresivno"
31
-AMF.H264.ScanType.Interlaced="Isprekidano"
32
 AMF.H264.RateControlMethod="Metoda kontrole protoka"
33
 AMF.H264.RateControlMethod.CQP="Konstantan kvalitet (CQP)"
34
 AMF.H264.RateControlMethod.CBR="Konstantan protok (CBR)"
35
@@ -30,15 +36,12 @@
36
 AMF.H264.QP.IFrame="I-Frejm QP"
37
 AMF.H264.QP.PFrame="P-Frejm QP"
38
 AMF.H264.QP.BFrame="B-Frejm QP"
39
-AMF.H264.QP.BPictureDelta="B-Promena slike QP"
40
-AMF.H264.QP.ReferenceBPictureDelta="Referenca B-Promena slike QP"
41
 AMF.H264.FillerData="Podaci za popunjavanje"
42
 AMF.H264.FrameSkipping="Preskakanje frejmova"
43
 AMF.H264.EnforceHRDCompatibility="Prisilna HRD kompatibilnost"
44
-AMF.H264.BPicture.Pattern="B-Šablonska slika"
45
-AMF.H264.BPicture.Reference="B-Referentna slika"
46
 AMF.H264.DeblockingFilter="Odblokirajući filter"
47
-AMF.Util.Default="Podrazumevano"
48
-AMF.Util.Automatic="Automatski"
49
-AMF.Util.Toggle.Disabled="Onemogućeno"
50
-AMF.Util.Toggle.Enabled="Omogućeno"
51
+AMF.H264.ScanType="Vrsta skeniranja"
52
+AMF.H264.ScanType.Progressive="Progresivno"
53
+AMF.H264.ScanType.Interlaced="Isprekidano"
54
+AMF.H264.MaximumLTRFrames="Maksimalan broj LTR frejmova"
55
+
56
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/sr-SP.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/sr-SP.ini Changed
39
 
1
@@ -1,3 +1,7 @@
2
+AMF.Util.Default="Подразумевано"
3
+AMF.Util.Automatic="Аутоматски"
4
+AMF.Util.Toggle.Disabled="Онемогућено"
5
+AMF.Util.Toggle.Enabled="Омогућено"
6
 AMF.H264.Usage.Transcoding="Транскодирање"
7
 AMF.H264.Usage.UltraLowLatency="Ултра ниско кашњење"
8
 AMF.H264.Usage.LowLatency="Ниско кашњење"
9
@@ -7,9 +11,6 @@
10
 AMF.H264.QualityPreset.Quality="Квалитет"
11
 AMF.H264.Profile="Профил"
12
 AMF.H264.ProfileLevel="Ниво профила"
13
-AMF.H264.ScanType="Врста скенирања"
14
-AMF.H264.ScanType.Progressive="Прогресивно"
15
-AMF.H264.ScanType.Interlaced="Испрекидано"
16
 AMF.H264.RateControlMethod="Метода контроле протока"
17
 AMF.H264.RateControlMethod.CQP="Константан квалитет (CQP)"
18
 AMF.H264.RateControlMethod.CBR="Константан проток (CBR)"
19
@@ -22,15 +23,11 @@
20
 AMF.H264.QP.IFrame="I-Фрејм QP"
21
 AMF.H264.QP.PFrame="P-Фрејм QP"
22
 AMF.H264.QP.BFrame="B-Фрејм QP"
23
-AMF.H264.QP.BPictureDelta="B-Промена слике QP"
24
-AMF.H264.QP.ReferenceBPictureDelta="Референца B-Промена слике QP"
25
 AMF.H264.FillerData="Подаци за попуњавање"
26
 AMF.H264.FrameSkipping="Прескакање фрејмова"
27
 AMF.H264.EnforceHRDCompatibility="Присилна HRD компатибилност"
28
-AMF.H264.BPicture.Pattern="B-Шаблонска слика"
29
-AMF.H264.BPicture.Reference="B-Референтна слика"
30
 AMF.H264.DeblockingFilter="Одблокирајући филтер"
31
-AMF.Util.Default="Подразумевано"
32
-AMF.Util.Automatic="Аутоматски"
33
-AMF.Util.Toggle.Disabled="Онемогућено"
34
-AMF.Util.Toggle.Enabled="Омогућено"
35
+AMF.H264.ScanType="Врста скенирања"
36
+AMF.H264.ScanType.Progressive="Прогресивно"
37
+AMF.H264.ScanType.Interlaced="Испрекидано"
38
+
39
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/sv-SE.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/sv-SE.ini Changed
73
 
1
@@ -1,40 +1,63 @@
2
+AMF.Util.Default="Standard"
3
+AMF.Util.Automatic="Automatisk"
4
+AMF.Util.Manual="Manuell"
5
+AMF.Util.Toggle.Disabled="Inaktiverad"
6
+AMF.Util.Toggle.Enabled="Aktiverad"
7
 AMF.H264.Preset="Förinställning"
8
+AMF.H264.Preset.ResetToDefaults="Återställ till standardvärden"
9
+AMF.H264.Preset.Recording="Spelar in"
10
 AMF.H264.Preset.HighQuality="Hög kvalitet"
11
 AMF.H264.Preset.Indistinguishable="Oskiljbar"
12
 AMF.H264.Preset.Lossless="Förlustfri"
13
 AMF.H264.Preset.Twitch="Twitch"
14
 AMF.H264.Preset.YouTube="YouTube"
15
 AMF.H264.Usage="Användning"
16
+AMF.H264.Usage.Description="Vilken användning AMF borde vara inställd på:\n- '\@AMF.H264.Usage.Transcoding\@' är för allmän omkodning (rekommenderas),\n- '\@AMF.H264.Usage.UltraLowLatency\@' är för omkodning med riktigt låg latens,\n- '\@AMF.H264.Usage.LowLatency\@' liknar ovanstående men med lite högre latens.\nStrömning stöder endast '\@AMF.H264.Usage.Transcoding\@', alla andra värden kan användas för inspelning."
17
 AMF.H264.Usage.Transcoding="Omkodning"
18
 AMF.H264.Usage.UltraLowLatency="Ultralåg latens"
19
 AMF.H264.Usage.LowLatency="Låg latens"
20
 AMF.H264.QualityPreset="Kvalitetsförinställning"
21
+AMF.H264.QualityPreset.Description="Vilken kvalitetsmall AMF bör försöka att uppnå:\n- '\@AMF.H264.QualityPreset.Speed\@' är den snabbaste men har den sämsta kvaliteten,\n- '\@AMF.H264.QualityPreset.Balanced\@' är en balanserad mix av båda,\n- '\@AMF.H264.QualityPreset.Quality\@' ger den bästa kvaliteten för en angiven bithastighet."
22
 AMF.H264.QualityPreset.Speed="Hastighet"
23
 AMF.H264.QualityPreset.Balanced="Balanserad"
24
 AMF.H264.QualityPreset.Quality="Kvalitet"
25
 AMF.H264.Profile="Profil"
26
+AMF.H264.Profile.Description="Vilken H.264-profil att använda för kodning:\n- 'Baseline' stödjer flest plattformar,\n- 'Main' stöds av äldre enheter (rekommenderas för mobila enheter),\n- 'High' stöds av aktuella enheter (rekommenderas)."
27
 AMF.H264.ProfileLevel="Profilnivå"
28
-AMF.H264.ScanType="Typ av skanning"
29
-AMF.H264.ScanType.Progressive="Progressiv"
30
-AMF.H264.ScanType.Interlaced="Sammanflätad"
31
+AMF.H264.ProfileLevel.Description="Vilken H.264-profilnivå att använda för kodning:\n- '\@AMF.Util.Automatic\@' beräknar den bästa profilnivån för den angivna bildfrekvensen och bildstorleken,\n- '4.1' stöder 1920x1080 30FPS, 1280x720 60FPS, 960x540 90FPS\n- '4.2' stöder 1920x1080 60FPS, 1280x720 120FPS, 960x540 172FPS\n- '5.0' stöder 1920x1080 60FPS, 1280x720 144FPS, 960x540 172FPS\n- '5.1' stöder 3840x2160 30FPS, 1920x1080 120FPS, 1280x720 172FPS, 960x540 172FPS\n- '5.2' stöder 3840x2160 60FPS, 1920x1080 172FPS, 1280x720 172FPS, 960x540 172FPS"
32
 AMF.H264.RateControlMethod.CQP="Konstant QP (CQP)"
33
 AMF.H264.RateControlMethod.CBR="Konstant bithastighet (CBR)"
34
 AMF.H264.Bitrate.Target="Målets bithastighet"
35
+AMF.H264.Bitrate.Target.Description="Bithastighet att försöka uppnå i den övergripande sekvensen."
36
 AMF.H264.Bitrate.Peak="Maximal bithastighet"
37
 AMF.H264.QP.Minimum="Minimal QP"
38
 AMF.H264.QP.Maximum="Maximal QP"
39
+AMF.H264.VBVBuffer="VBV-buffert"
40
+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."
41
+AMF.H264.VBVBuffer.Strictness="Strikthet för VBV-buffert"
42
+AMF.H264.VBVBuffer.Size="VBV-buffertstorlek"
43
 AMF.H264.FrameSkipping="Hoppa över bildrutor"
44
 AMF.H264.EnforceHRDCompatibility="Tvinga HRD-kompatibilitet"
45
+AMF.H264.IDRPeriod="IDR-period"
46
+AMF.H264.IDRPeriod.Description="Definierar avståndet mellan Instantaneous Decoding Refreshes (IDR) i bildrutor. Kontrollerar även GOP-sekvensens storlek."
47
 AMF.H264.DeblockingFilter="Avblockningsfilter"
48
+AMF.H264.ScanType="Typ av skanning"
49
+AMF.H264.ScanType.Description="Vilken skanningsmetod att använda, lämna alltid detta på '\@AMF.H264.ScanType.Progressive\@'."
50
+AMF.H264.ScanType.Progressive="Progressiv"
51
+AMF.H264.ScanType.Interlaced="Sammanflätad"
52
+AMF.H264.MotionEstimation="Rörelseuppskattning"
53
+AMF.H264.MotionEstimation.Description="Rörelseuppskattning låter kodaren reducera nödvändig bithastighet genom att uppskatta var en bildpunkt förflyttas."
54
 AMF.H264.MotionEstimation.None="Ingen"
55
+AMF.H264.MotionEstimation.Half="Halv bildpunkt"
56
+AMF.H264.MotionEstimation.Quarter="Fjärdedels bildpunkt"
57
+AMF.H264.MotionEstimation.Both="Halv och fjärdedels bildpunkt"
58
+AMF.H264.CodingType="Kodningstyp"
59
+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."
60
+AMF.H264.MaximumLTRFrames="Maximalt antal LTR-bildrutor"
61
 AMF.H264.View="Visningsläge"
62
 AMF.H264.View.Basic="Grundläggande"
63
 AMF.H264.View.Advanced="Avancerad"
64
 AMF.H264.View.Expert="Expert"
65
 AMF.H264.View.Master="Master"
66
 AMF.H264.Debug="Felsök"
67
-AMF.Util.Default="Standard"
68
-AMF.Util.Automatic="Automatisk"
69
-AMF.Util.Manual="Manuell"
70
-AMF.Util.Toggle.Disabled="Inaktiverad"
71
-AMF.Util.Toggle.Enabled="Aktiverad"
72
+
73
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/uk-UA.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/uk-UA.ini Changed
122
 
1
@@ -1,3 +1,8 @@
2
+AMF.Util.Default="За замовчанням"
3
+AMF.Util.Automatic="Автоматично"
4
+AMF.Util.Manual="Вручну"
5
+AMF.Util.Toggle.Disabled="Вимкнено"
6
+AMF.Util.Toggle.Enabled="Увімкнено"
7
 AMF.H264.Preset="Шаблон"
8
 AMF.H264.Preset.ResetToDefaults="Відновити параметри за замовчанням"
9
 AMF.H264.Preset.Recording="Звичайний запис"
10
@@ -20,12 +25,6 @@
11
 AMF.H264.Profile.Description="Зазначений профіль H.264 буде використано енкодером:\n  'Baseline' - найпоширеніший серед пристроїв відтворення\n  'Main' - майже всі пристрої відтворення мають підтримку цього профілю\n  'High' - профіль підтримується найсучаснішими пристроями (рекомендується)."
12
 AMF.H264.ProfileLevel="Рівень профілю"
13
 AMF.H264.ProfileLevel.Description="Визначає рівень профілю H.264 який буде використано під час кодування:\n  'Автоматично' - програма сама встановить найкращій рівень профілю згідно розміру та частоти кадрів,\n  '4.1' - підтримує 1920x1080 30 кадрів/с, 1280x720 60 кадрів/с, 960x540 90 кадрів/с\n  '4.2' - підтримує 1920x1080 60 кадрів/с, 1280x720 120 кадрів/с, 960x540 172 кадрів/с\n  '5.0' - підтримує 1920x1080 60 кадрів/с, 1280x720 144 кадрів/с, 960x540 172 кадрів/с\n  '5.1' - підтримує 3840x2160 30 кадрів/с, 1920x1080 120 кадрів/с, 1280x720 172 кадрів/с, 960x540 172 кадрів/с\n  '5.2' - підтримує 3840x2160 60 кадрів/с, 1920x1080 172 кадрів/с, 1280x720 172 кадрів/с, 960x540 172 кадрів/с"
14
-AMF.H264.MaximumLTRFrames="Кількість LTR-кадрів контрольованих користувачем"
15
-AMF.H264.MaximumLTRFrames.Description="Long-Term Reference (LTR) кадри дозволяють при кодуванні маркувати декілька кадрів як опорні для інших.\nЦе може поліпшити якість у разі відсутності підтримки B-кадрів або небажаності їх використання.\nЯкщо 'Кількість LTR-кадрів контрольованих користувачем' вказано, то енкодер не підтримуватиме B-кадри у відео."
16
-AMF.H264.ScanType="Вид розгортки"
17
-AMF.H264.ScanType.Description="Визначає вид розгортки який треба використовувати у кодуванні,\nзавжди користуйтеся значенням 'Прогресивна'."
18
-AMF.H264.ScanType.Progressive="Прогресивна"
19
-AMF.H264.ScanType.Interlaced="Черезрядкова"
20
 AMF.H264.RateControlMethod="Метод керування потоком"
21
 AMF.H264.RateControlMethod.Description="Визначає метод керування потоком:\n  'Фіксований QP (CQP)' - встановлює фіксовані QP для I-/P-/B-кадрів,\n  'Постійний бітрейт (CBR)' - дотримується значення Бажаний бітрейт потоку (використовуючи\nопцію Заповнювати пустоти у бітрейту) (рекомендується для трансляцій),\n  'Змінний бітрейт (максимальний бітрейт обмежено) (VBR)' - потік завжди залишається нижче значення Максимальний бітрейт,\n  'Змінний бітрейт (затримку обмежено) (VBR_LAT)' - потік буде збережено близько до значення Бажаний бітрейт,\nдопоки затримка графічного адаптеру та навантаження на нього дозволятимуть це,\nв іншому випадку бітрейт буде збільшено (рекомендується для запису).\n\nQP - Quantization Parameter (параметр квантування)."
22
 AMF.H264.RateControlMethod.CQP="Фіксований QP (CQP)"
23
@@ -41,21 +40,17 @@
24
 AMF.H264.QP.Maximum="Максимальний QP"
25
 AMF.H264.QP.Maximum.Description="Найвищий QP (параметр квантування) в кадрі."
26
 AMF.H264.QP.IFrame="QP для I-кадрів"
27
-AMF.H264.QP.IFrame.Description="Фіксоване значення QP (параметр квантування) для I-кадрів.\nQP для I-кадрів повинно бути на рівні або вище за QP для P- та B-кадрів."
28
+AMF.H264.QP.IFrame.Description="Фіксоване значення QP (параметр квантування) для I-кадрів."
29
 AMF.H264.QP.PFrame="QP для P-кадрів"
30
-AMF.H264.QP.PFrame.Description="Фіксоване значення QP (параметр квантування) для P-кадрів.\nQP для P-кадрів повинно бути на рівні або вище за QP для B-кадрів."
31
+AMF.H264.QP.PFrame.Description="Фіксоване значення QP (параметр квантування) для P-кадрів."
32
 AMF.H264.QP.BFrame="QP для B-кадрів"
33
 AMF.H264.QP.BFrame.Description="Фіксоване значення QP (параметр квантування) для B-кадрів."
34
-AMF.H264.QP.BPictureDelta="B-кадри, відхил QP"
35
-AMF.H264.QP.BPictureDelta.Description="Відхил QP (параметра квантування) для не опорних B-кадрів, по відношенню до I-кадрів."
36
-AMF.H264.QP.ReferenceBPictureDelta="Опорні B-кадри, відхил QP"
37
-AMF.H264.QP.ReferenceBPictureDelta.Description="Відхил QP (параметра квантування) для порних B-кадрів, по відношенню до I-кадрів."
38
 AMF.H264.VBVBuffer="Буфер VBV"
39
 AMF.H264.VBVBuffer.Description="Метод, що використовується для визначення параметру Розмір VBV буфера:\n  'Автоматично' - енкодер вираховує розмір враховуючи параметр Буфер VBV, кореляція.\n  'Вручну' - дозволяє користувачеві контролювати цей розмір.\nVBV (Video Buffering Verifier) Буфер використовується різними Методами керування потоком для збереження бітрейту у зазначених межах."
40
 AMF.H264.VBVBuffer.Strictness="Буфер VBV, кореляція"
41
-AMF.H264.VBVBuffer.Strictness.Description="Визначає як близько значення Буфер VBV дорівнюють значенню Бажаний бітрейт, у відсотках."
42
+AMF.H264.VBVBuffer.Strictness.Description="Визначає як близько значення Буфер VBV дорівнює заданому, у відсотках."
43
 AMF.H264.VBVBuffer.Size="Розмір VBV буфера"
44
-AMF.H264.VBVBuffer.Size.Description="Розмір VBV буфера (Video Buffering Verifier) використовується під час контролю бітрейта відео.\nМалі значення дозволяють цілком збігатися зі встановленим бітрейтом але здійснюють додаткове навантаження."
45
+AMF.H264.VBVBuffer.Size.Description="Розмір VBV буфера (Video Buffering Verifier) використовується під час контролю бітрейта відео."
46
 AMF.H264.VBVBuffer.Fullness="Початкова повнота буферу VBV"
47
 AMF.H264.VBVBuffer.Fullness.Description="Визначає початкову заповнюваність Буферу VBV, діє лише на початку кодування."
48
 AMF.H264.FillerData="Заповнювати пустоти у бітрейту"
49
@@ -64,46 +59,49 @@
50
 AMF.H264.FrameSkipping.Description="Пропускати кадри - дозволяє енкодеру відкидати кадри, якщо керування потоком не може досягти встановленого значення Бажаний бітрейт.\nКоли енкодер пропускає кадр, він додає дублювати-останній-кадр NAL до потоку.\nМоже допомогти при встановленні дуже низьких значень Бажаний бітрейт."
51
 AMF.H264.EnforceHRDCompatibility="Застосувати примусову сумісність з HRD"
52
 AMF.H264.EnforceHRDCompatibility.Description="Застосувати примусову сумісність з HRD (Hypothetical Reference Decoder) - накладає обмеження на максимальне значення QP (параметра квантування) у кадрі задля досягнення сумісності з HRD.\nНе рекомендується для записів або трансляцій. Використовувати лише для сумісності з найстарішими пристроями які мають лише базовий декодер."
53
-AMF.H264.MaximumAccessUnitSize="Максимальний розмір Access Unit"
54
-AMF.H264.MaximumAccessUnitSize.Description="Визначає максимальний розмір Access Unit для NAL. Значення 0 дозволяє енкодеру обирати найкращий розмір самостійно."
55
 AMF.H264.KeyframeInterval="Інтервал ключових кадрів"
56
 AMF.H264.KeyframeInterval.Description="Визначає кількість секунд між двома повними кадрами (ключовими кадрами).\nТакож контролює довжину послідовності кадрів у групі зображень (GOP)."
57
 AMF.H264.IDRPeriod="IDR, період (кадрів)"
58
 AMF.H264.IDRPeriod.Description="Визначає відстань між Instantaneous Decoding Refreshes (IDR) (ключовими кадрами), в кадрах.\nТакож контролює довжину послідовності кадрів у групі зображень (GOP)."
59
-AMF.H264.HeaderInsertionSpacing="Заголовки потоку, період (кадрів)"
60
-AMF.H264.HeaderInsertionSpacing.Description="Визначає скільки кадрів повинно бути між NAL заголовками. Не рекомендується змінювати цей параметр від значення 0 (автоматично)."
61
-AMF.H264.BPicture.Pattern="Послідовні B-кадри"
62
-AMF.H264.BPicture.Pattern.Description="Визначає кількість дозволених B-кадрів у кодуванні. Має позитивний вплив на якість зображення та негативний на продуктивність.\nПідтримується принаймні 2-м та 3-м поколінням VCE карт."
63
-AMF.H264.BPicture.Reference="B-кадри як опорні"
64
-AMF.H264.BPicture.Reference.Description="Дозволяє робити B-кадри опорними для інших B-кадрів в додаток до вже існуючих P- та I-кадрів.\nЗдійснює величезне навантаження, при незначному поліпшенні якості."
65
+AMF.H264.BFrame.Pattern="B-кадри"
66
+AMF.H264.BFrame.Pattern.Description="Визначає кількість послідовних B-кадрів у кодуванні.\nПідтримується принаймні 2-м та 3-м поколінням VCE карт. Маєнегативний вплив на продуктивність."
67
+AMF.H264.BFrame.DeltaQP="B-кадри, відхил QP"
68
 AMF.H264.DeblockingFilter="Деблокінг-фільтр"
69
 AMF.H264.DeblockingFilter.Description="Встановлює позначку, що дозволяє декодеру використовувати Деблокінг-фільтр для цього відео."
70
-AMF.H264.SlicesPerFrame="Фрагментів на кадр"
71
-AMF.H264.SlicesPerFrame.Description="Скільки фрагментів I-кадрів буде у кожному кадру?\nНульове значення дозволяє енкодеру визначати цю кількість під час кодування самостійно.\nIntra-Refresh кодування використовується для більш швидкого відтворення та навігації."
72
-AMF.H264.IntraRefreshNumMBsPerSlot="Кількість Intra-Refresh макроблоків на слот"
73
-AMF.H264.IntraRefreshNumMBsPerSlot.Description="Скільки Intra-Refresh макроблоків буде у кожному слоті?\nНульове значення дозволяє енкодеру визначати цю кількість під час кодування самостійно.\nIntra-Refresh кодування використовується для більш швидкого відтворення та навігації."
74
+AMF.H264.ScanType="Вид розгортки"
75
+AMF.H264.ScanType.Description="Визначає вид розгортки який треба використовувати у кодуванні,\nзавжди користуйтеся значенням 'Прогресивна'."
76
+AMF.H264.ScanType.Progressive="Прогресивна"
77
+AMF.H264.ScanType.Interlaced="Черезрядкова"
78
 AMF.H264.MotionEstimation="Оцінка руху"
79
 AMF.H264.MotionEstimation.Description="Оцінка руху дозволяє енкодеру зменшити вимоги до бітрейту завдяки розрахункам з переміщення пікселів."
80
 AMF.H264.MotionEstimation.None="Немає"
81
 AMF.H264.MotionEstimation.Half="Пів-пікселя"
82
 AMF.H264.MotionEstimation.Quarter="Чверть-пікселя"
83
 AMF.H264.MotionEstimation.Both="Пів-пікселя та Чверть-пікселя"
84
-AMF.H264.Device="Пристрій"
85
-AMF.H264.Device.Description="Визначає Пристрій що буде використано у кодуванні.\nПотребує встановити параметр Пам'ять адресується у значення відмінне від 'Host'."
86
-AMF.H264.UseOpenCL="Використовувати OpenCL"
87
-AMF.H264.UseOpenCL.Description="Чи буде енкодер використовувати OpenCL щоб надсилати кожен окремий кадр?"
88
+AMF.H264.CodingType="Схема кодування"
89
+AMF.H264.CodingType.Description="Визначає яку схему кодування використовувати:\n  'За замовчанням' - програма вирішує самостійно (рекомендується).\n  'CABAC' - контекстно-залежне адаптивне бінарне арифметичне кодування, схема має кращу компресію даних, але здійснює більше навантаження.\n  'CAVLC' - контекстно-залежне адаптивне кодування із змінною довжиною кодового слова, схема має дещо меншу компресію даних, але й здійснює менше навантаження."
90
+AMF.H264.MaximumLTRFrames="Кількість LTR-кадрів контрольованих користувачем"
91
+AMF.H264.MaximumLTRFrames.Description="Long-Term Reference (LTR) кадри дозволяють при кодуванні маркувати декілька кадрів як опорні для інших.\nЯкщо 'Кількість LTR-кадрів контрольованих користувачем' вказано, то енкодер не підтримуватиме B-кадри у відео."
92
+AMF.H264.MaximumAccessUnitSize="Максимальний розмір Access Unit"
93
+AMF.H264.MaximumAccessUnitSize.Description="Визначає максимальний розмір Access Unit для NAL. Значення 0 дозволяє енкодеру обирати найкращий розмір самостійно."
94
+AMF.H264.HeaderInsertionSpacing="Заголовки потоку, період (кадрів)"
95
+AMF.H264.HeaderInsertionSpacing.Description="Визначає скільки кадрів повинно бути між NAL заголовками. Не рекомендується змінювати цей параметр від значення 0 (автоматично)."
96
+AMF.H264.GOPSize="Розмір GOP"
97
+AMF.H264.MaximumReferenceFrames="Максимальна кількість опорних кадрів"
98
+AMF.H264.SlicesPerFrame="Фрагментів на кадр"
99
+AMF.H264.SlicesPerFrame.Description="Скільки фрагментів I-кадрів буде у кожному кадру?\nНульове значення дозволяє енкодеру визначати цю кількість під час кодування самостійно.\nIntra-Refresh кодування використовується для більш швидкого відтворення та навігації."
100
+AMF.H264.IntraRefresh.NumberOfStripes="Кількість рядків Intra-Refresh"
101
+AMF.H264.IntraRefresh.MacroblocksPerSlot="Кількість Intra-Refresh макроблоків на слот"
102
+AMF.H264.VideoAdapter="Відеоадаптер"
103
+AMF.H264.VideoAdapter.Description="Визначає який відеоадаптер використовувати для кодування."
104
+AMF.H264.OpenCL="OpenCL"
105
+AMF.H264.OpenCL.Description="Чи буде енкодер використовувати OpenCL щоб надсилати кожен окремий кадр?"
106
 AMF.H264.View="Вид для налаштувань"
107
 AMF.H264.View.Description="Визначає кількість наявних опцій для налаштування. Навряд чи розробник вам допомагатиме, якщо ви оберете рівень 'Експерт' або 'Бог енкодерів'."
108
 AMF.H264.View.Basic="Базовий"
109
 AMF.H264.View.Advanced="Розширений"
110
 AMF.H264.View.Expert="Експерт"
111
 AMF.H264.View.Master="Бог енкодерів"
112
-AMF.H264.UnlockProperties="Розширити ввод параметрів"
113
-AMF.H264.UnlockProperties.Description="Дозволяє вводити деякі параметри у їх необробленому виді, тобто без\nперерахунків на Кбайтність/Кбітність та без деяких обмежень."
114
 AMF.H264.Debug="Відладка"
115
 AMF.H264.Debug.Description="Вмикає занесення до лог-файлу додаткової інформації про процес кодування. Корисно у випадку коли ви бажаєте звернутися за допомогою до розробника енкодера."
116
-AMF.Util.Default="За замовчанням"
117
-AMF.Util.Automatic="Автоматично"
118
-AMF.Util.Manual="Вручну"
119
-AMF.Util.Toggle.Disabled="Вимкнено"
120
-AMF.Util.Toggle.Enabled="Увімкнено"
121
+
122
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/vi-VN.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/vi-VN.ini Changed
69
 
1
@@ -1,10 +1,17 @@
2
+AMF.Util.Default="Mặc định"
3
+AMF.Util.Automatic="Tự động"
4
+AMF.Util.Manual="Thủ công"
5
+AMF.Util.Toggle.Disabled="Tắt"
6
+AMF.Util.Toggle.Enabled="Bật"
7
 AMF.H264.Preset="Mẫu thiết lập"
8
+AMF.H264.Preset.ResetToDefaults="Thiết lập về mặc định"
9
 AMF.H264.Preset.Recording="Quay video"
10
 AMF.H264.Preset.HighQuality="Chất lượng cao"
11
 AMF.H264.Preset.Indistinguishable="Không thể phân biệt"
12
 AMF.H264.Preset.Lossless="Lossless"
13
 AMF.H264.Preset.Twitch="Twitch"
14
 AMF.H264.Preset.YouTube="YouTube"
15
+AMF.H264.Usage="Sử dụng"
16
 AMF.H264.Usage.Transcoding="Chuyển mã"
17
 AMF.H264.Usage.UltraLowLatency="Độ trễ cực thấp"
18
 AMF.H264.Usage.LowLatency="Độ trễ thấp"
19
@@ -14,10 +21,6 @@
20
 AMF.H264.QualityPreset.Quality="Chất lượng"
21
 AMF.H264.Profile="Profile"
22
 AMF.H264.ProfileLevel="Profile Level"
23
-AMF.H264.MaximumLTRFrames="LTR Frames tối đa"
24
-AMF.H264.ScanType="Quét hình loại"
25
-AMF.H264.ScanType.Progressive="Quét nguyên ảnh (Progressive)"
26
-AMF.H264.ScanType.Interlaced="Quét 1/2 ảnh (Interlaced)"
27
 AMF.H264.RateControlMethod="Cách kiểm soát Bitrate"
28
 AMF.H264.RateControlMethod.CQP="QP Không thay đổi (CQP)"
29
 AMF.H264.RateControlMethod.CBR="Bitrate Không thay đổi (CBR)"
30
@@ -30,31 +33,27 @@
31
 AMF.H264.QP.IFrame="I-Frame QP"
32
 AMF.H264.QP.PFrame="P-Frame QP"
33
 AMF.H264.QP.BFrame="B-Frame QP"
34
-AMF.H264.QP.BPictureDelta="B-Picture Delta QP"
35
-AMF.H264.QP.ReferenceBPictureDelta="Reference B-Picture Delta QP"
36
 AMF.H264.FillerData="Filler Data (Thêm data cho đủ bitrate)"
37
 AMF.H264.FrameSkipping="Frame Skipping"
38
 AMF.H264.EnforceHRDCompatibility="Enforce HRD Compatibility"
39
 AMF.H264.KeyframeInterval="Thời gian đặt keyframe"
40
-AMF.H264.BPicture.Pattern="B-Picture Pattern"
41
-AMF.H264.BPicture.Reference="B-Picture Reference"
42
 AMF.H264.DeblockingFilter="De-blocking Filter (Lọc chống nhiễu ảnh)"
43
-AMF.H264.SlicesPerFrame="Lát cho mỗi khung hình"
44
+AMF.H264.ScanType="Quét hình loại"
45
+AMF.H264.ScanType.Progressive="Quét nguyên ảnh (Progressive)"
46
+AMF.H264.ScanType.Interlaced="Quét 1/2 ảnh (Interlaced)"
47
 AMF.H264.MotionEstimation="Dự đoán bù trừ chuyển động"
48
 AMF.H264.MotionEstimation.Description="Dự toán chuyển động cho phép bộ mã hóa giảm bitrate cần thiết bằng cách ước tính một pixel sẽ đi đâu."
49
 AMF.H264.MotionEstimation.None="Không"
50
 AMF.H264.MotionEstimation.Half="1/2 Pixel"
51
 AMF.H264.MotionEstimation.Quarter="1/4 Pixel"
52
 AMF.H264.MotionEstimation.Both="1/2 và 1/4 Pixel"
53
+AMF.H264.CodingType="Coding Type"
54
+AMF.H264.MaximumLTRFrames="LTR Frames tối đa"
55
+AMF.H264.SlicesPerFrame="Lát cho mỗi khung hình"
56
 AMF.H264.View="Chế độ xem"
57
 AMF.H264.View.Basic="Cơ bản"
58
 AMF.H264.View.Advanced="Nâng cao"
59
 AMF.H264.View.Expert="Chuyên gia"
60
 AMF.H264.View.Master="Bật cả tính năng ẩn"
61
-AMF.H264.UnlockProperties="Mở khóa Properties"
62
 AMF.H264.Debug="Gỡ lỗi"
63
-AMF.Util.Default="Mặc định"
64
-AMF.Util.Automatic="Tự động"
65
-AMF.Util.Manual="Thủ công"
66
-AMF.Util.Toggle.Disabled="Tắt"
67
-AMF.Util.Toggle.Enabled="Bật"
68
+
69
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/zh-CN.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/zh-CN.ini Changed
149
 
1
@@ -1,3 +1,8 @@
2
+AMF.Util.Default="默认"
3
+AMF.Util.Automatic="自动"
4
+AMF.Util.Manual="手动"
5
+AMF.Util.Toggle.Disabled="禁用"
6
+AMF.Util.Toggle.Enabled="启用"
7
 AMF.H264.Preset="预设"
8
 AMF.H264.Preset.ResetToDefaults="重置为默认值"
9
 AMF.H264.Preset.Recording="录像"
10
@@ -20,12 +25,6 @@
11
 AMF.H264.Profile.Description="H.264的编码选项有:\n-'Baseline' 支持的平台最广,\n-'Main' 支持较老的设备(如果使用的平台是手机,推荐使用),\n-'High' 被当下的设备支持(推荐使用)。"
12
 AMF.H264.ProfileLevel="配置等级"
13
 AMF.H264.ProfileLevel.Description="对于编码使用哪种 H.264 Profile Level:\n-'Automatic' 根据给定的帧率和帧大小计算最优的 profile level,\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"
14
-AMF.H264.MaximumLTRFrames="最大的 LTR 帧"
15
-AMF.H264.MaximumLTRFrames.Description="长期参考帧(LTR) 是一个特性允许编码器来标记在一个序列的一些帧作为参考帧.\n这会使当 B 帧不支持或者不需要时提高质量.\nLTR真不能和 B 帧一起使用, 并且当使用LTR时, 编码器会禁用 B 帧."
16
-AMF.H264.ScanType="扫描类型"
17
-AMF.H264.ScanType.Description="使用哪种扫描方法, 通常设置为'Progressive'."
18
-AMF.H264.ScanType.Progressive="渐进"
19
-AMF.H264.ScanType.Interlaced="交错"
20
 AMF.H264.RateControlMethod="速率控制方法"
21
 AMF.H264.RateControlMethod.Description="该使用什么调节码率的方法:\n- '\@AMF.H264.RateControlMethod.CQP\@' assigns fixed I-/P-/B-Frame QP (Quantization Parameter) values,\n- '\@AMF.H264.RateControlMethod.CBR\@' stays at the given Target Bitrate (using Filler Data) (推荐推流使用),\n- '\@AMF.H264.RateControlMethod.VBR\@' stays below the given Peak Bitrate,\n- '\@AMF.H264.RateControlMethod.VBR_LAT\@' stays close to the Target Bitrate if GPU latency and load allow for it, otherwise will use higher bitrate (推荐录像使用)."
22
 AMF.H264.RateControlMethod.CQP="恒定 QP (CQP)"
23
@@ -41,21 +40,17 @@
24
 AMF.H264.QP.Maximum="最高 QP"
25
 AMF.H264.QP.Maximum.Description="一帧中最高 QP (量化参数) 值"
26
 AMF.H264.QP.IFrame="I 帧 QP"
27
-AMF.H264.QP.IFrame.Description="用于 I 帧的固定 QP (量化参数) 值.\nI帧 QP值应该大于等于 P B 帧的 QP 值."
28
+AMF.H264.QP.IFrame.Description="用于 I 帧的固定的 QP 值."
29
 AMF.H264.QP.PFrame="P 帧 QP"
30
-AMF.H264.QP.PFrame.Description="用于 P 帧的固定 QP (量化参数) 值.\nP帧 QP值应该大于等于 B 帧的 QP 值."
31
+AMF.H264.QP.PFrame.Description="用于 P 帧的固定 QP 值."
32
 AMF.H264.QP.BFrame="B 帧 QP"
33
 AMF.H264.QP.BFrame.Description="用于 B 帧的固定 QP (量化参数) 值."
34
-AMF.H264.QP.BPictureDelta="B 图片 差值 QP"
35
-AMF.H264.QP.BPictureDelta.Description="相对于上一个非参考 B 帧的差值 QP 值."
36
-AMF.H264.QP.ReferenceBPictureDelta="参考 B 图片 差值 QP"
37
-AMF.H264.QP.ReferenceBPictureDelta.Description="相对于上一个参考 B 帧的差值 QP 值."
38
 AMF.H264.VBVBuffer="VBV 缓存"
39
 AMF.H264.VBVBuffer.Description="应使用什么方法来确定 VBV 缓冲区大小:\n-'自动' 计算使用严格约束的大小,\n- '手册' 允许用户控制大小.\nVBV缓存 (视频缓冲程序验证程序) 用于某些率控制方法来保持整体的比特率在给定的约束内."
40
 AMF.H264.VBVBuffer.Strictness="VBV 缓存规范性"
41
-AMF.H264.VBVBuffer.Strictness.Description="VBV 缓存应该怎样严格, 100% 几乎完全和目标比特率一致和 0% 不受限制的."
42
+AMF.H264.VBVBuffer.Strictness.Description="决定 VBV 缓存的严格性, 100% 表示尽可能严格, 0% 表示无限制."
43
 AMF.H264.VBVBuffer.Size="VBV 缓存大小"
44
-AMF.H264.VBVBuffer.Size.Description="VBV 缓存大小用于在一个序列中的比特率控制.\n小缓存会导致几乎完美的比特率控制但有较大的性能影响."
45
+AMF.H264.VBVBuffer.Size.Description="用于在一个序列中的控制比特率的 VBV 缓存的大小."
46
 AMF.H264.VBVBuffer.Fullness="VBV 缓冲满"
47
 AMF.H264.VBVBuffer.Fullness.Description="VBV 缓存最初应该多满, 将只会影响最初的序列的编码."
48
 AMF.H264.FillerData="填充数据"
49
@@ -64,46 +59,76 @@
50
 AMF.H264.FrameSkipping.Description="跳过的帧允许编码器下丢帧, 以满足目标比特率要求.\n当编码器丢帧时, 它反而插入一个重复最后一帧的 NAL 到流中.\n可以帮助非常低的目标比特率."
51
 AMF.H264.EnforceHRDCompatibility="强制 HRD 兼容"
52
 AMF.H264.EnforceHRDCompatibility.Description="强制假设的参考解码器限制在一个帧内的最大的 QP 值更改.\n不推荐用于录制或推流, 并且应仅用于面向只有参考软件解码器的很老的设备."
53
-AMF.H264.MaximumAccessUnitSize="最大访问单元大小"
54
-AMF.H264.MaximumAccessUnitSize.Description="一个 NAL 的访问单元的最大大小. 值 0 允许编码器挑选最好的一个."
55
 AMF.H264.KeyframeInterval="关键帧间隔"
56
 AMF.H264.KeyframeInterval.Description="非丢弃帧之间应该多少秒.\n也控制序列(GOP) 的大小."
57
 AMF.H264.IDRPeriod="IDR 周期"
58
 AMF.H264.IDRPeriod.Description="定义的帧内瞬时解码刷新 (IDR) 的距离. 也控制 GOP 序列长度."
59
-AMF.H264.HeaderInsertionSpacing="头部插入空白"
60
-AMF.H264.HeaderInsertionSpacing.Description="NAL 头之间应该多少帧. 不推荐改为非零(自动) 值."
61
-AMF.H264.BPicture.Pattern="B 图片模式"
62
-AMF.H264.BPicture.Pattern.Description="应该允许编码多少 B 帧, 对质量有好处和对性能有坏处.\n第二代和第三代 VCE 卡支持."
63
-AMF.H264.BPicture.Reference="B 图片参考"
64
-AMF.H264.BPicture.Reference.Description="允许 B 帧参考 P 帧和 I 帧之外的其他 B 帧.\n 巨大的性能影响, 较小的质量提高."
65
+AMF.H264.BFrame.Pattern="B 帧"
66
+AMF.H264.BFrame.Pattern.Description="多少 B 帧应该用于编码.\n2 代和 3 代 VCE 卡支持. 对编码性能有负面影响."
67
+AMF.H264.BFrame.DeltaQP="B 帧差值 QP"
68
+AMF.H264.BFrame.DeltaQP.Description="对于非参考 B 帧, 相对于上一个 I 或者 P 帧的差值 QP 值."
69
+AMF.H264.BFrame.Reference="参考 B 帧"
70
+AMF.H264.BFrame.Reference.Description="允许 B 帧也使用 B 帧作为参考, 而不是只是 P 和 I 帧."
71
+AMF.H264.BFrame.ReferenceDeltaQP="参考 B 帧差值 QP"
72
+AMF.H264.BFrame.ReferenceDeltaQP.Description="对于参考 B 帧, 相对于上一个 I 或者 P 帧的差值 QP 值."
73
 AMF.H264.DeblockingFilter="去块滤波"
74
 AMF.H264.DeblockingFilter.Description="设置解码器允许使用的标记, 用于编码流去块滤波器."
75
-AMF.H264.SlicesPerFrame="每帧的切片数"
76
-AMF.H264.SlicesPerFrame.Description="每个帧应该和多少 I 帧切片一起存储?\n0 值让编码器运行时决定.\n内部刷新编码用于更快的回放和定位."
77
-AMF.H264.IntraRefreshNumMBsPerSlot="每个槽的内部宏块刷新数量"
78
-AMF.H264.IntraRefreshNumMBsPerSlot.Description="每个槽应该和多少宏块一起存储?\n0 值让编码器在运行时决定.\n帧内刷新编码用于更快的回放和定位."
79
+AMF.H264.ScanType="扫描类型"
80
+AMF.H264.ScanType.Description="使用哪种扫描方法, 通常设置为'Progressive'."
81
+AMF.H264.ScanType.Progressive="渐进"
82
+AMF.H264.ScanType.Interlaced="交错"
83
 AMF.H264.MotionEstimation="移动侦测"
84
 AMF.H264.MotionEstimation.Description="运动侦测允许编码器通过估计一个像素去了哪里来降低比特率."
85
 AMF.H264.MotionEstimation.None="无"
86
 AMF.H264.MotionEstimation.Half="半像素"
87
 AMF.H264.MotionEstimation.Quarter="四分之一像素"
88
 AMF.H264.MotionEstimation.Both="半&四分之一像素"
89
-AMF.H264.Device="设备"
90
-AMF.H264.Device.Description="哪个设备用来编码.\n需要内存类型不能设置为'主机'."
91
-AMF.H264.UseOpenCL="使用 OpenCL"
92
-AMF.H264.UseOpenCL.Description="编码器应该使用 OpenCL 提交单独的帧吗?"
93
+AMF.H264.CodingType="编码类型"
94
+AMF.H264.CodingType.Description="使用哪种编码类型:\n* \@AMF.Util.Default\@ 让 AMF 决定(推荐).\n* CALVC(上下文自适应可变长度编码) 速度更快但是更大.\n* CABAC(上下文自适应二进制算术编码)速度更慢, 但是更小."
95
+AMF.H264.MaximumLTRFrames="最大的 LTR 帧"
96
+AMF.H264.MaximumLTRFrames.Description="长期参考帧(LTR) 是一个特性允许编码器来标记在一个序列的一些帧作为参考帧一段时间.\nLTR 帧不能和 B 帧一起使用并且如果使用 LTR 帧, 编码器会禁用 B 帧."
97
+AMF.H264.MaximumAccessUnitSize="最大访问单元大小"
98
+AMF.H264.MaximumAccessUnitSize.Description="一个 NAL 的访问单元的最大大小. 值 0 允许编码器挑选最好的一个."
99
+AMF.H264.HeaderInsertionSpacing="头部插入空白"
100
+AMF.H264.HeaderInsertionSpacing.Description="NAL 头之间应该多少帧. 不推荐改为非零(自动) 值."
101
+AMF.H264.WaitForTask="等待任务"
102
+AMF.H264.WaitForTask.Description="未知, 实验"
103
+AMF.H264.PreAnalysisPass="预分析通过"
104
+AMF.H264.PreAnalysisPass.Description="未知, 实验"
105
+AMF.H264.VBAQ="VBAQ"
106
+AMF.H264.VBAQ.Description="未知, 实验"
107
+AMF.H264.GOPSize="GOP 大小"
108
+AMF.H264.GOPSize.Description="未知, 实验"
109
+AMF.H264.GOPAlignment="GOP 对齐"
110
+AMF.H264.GOPAlignment.Description="未知, 实验"
111
+AMF.H264.MaximumReferenceFrames="最大参考帧"
112
+AMF.H264.MaximumReferenceFrames.Description="未知, 实验"
113
+AMF.H264.SlicesPerFrame="每帧的切片数"
114
+AMF.H264.SlicesPerFrame.Description="每个帧应该和多少 I 帧切片一起存储?\n0 值让编码器运行时决定.\n内部刷新编码用于更快的回放和定位."
115
+AMF.H264.SliceMode="切片模式"
116
+AMF.H264.SliceMode.Description="未知, 实验"
117
+AMF.H264.MaximumSliceSize="最大切片大小"
118
+AMF.H264.MaximumSliceSize.Description="未知, 实验"
119
+AMF.H264.SliceControlMode="切片控制模式"
120
+AMF.H264.SliceControlMode.Description="未知, 实验"
121
+AMF.H264.SliceControlSize="切片控制大小"
122
+AMF.H264.SliceControlSize.Description="未知, 实验"
123
+AMF.H264.IntraRefresh.NumberOfStripes="帧内刷新的条纹的数目"
124
+AMF.H264.IntraRefresh.NumberOfStripes.Description="未知, 实验"
125
+AMF.H264.IntraRefresh.MacroblocksPerSlot="每个插槽的帧内刷新宏"
126
+AMF.H264.IntraRefresh.MacroblocksPerSlot.Description="每个槽应该和多少宏块一起存储?\n0 值让编码器在运行时决定.\n帧内刷新编码用于更快的回放和定位."
127
+AMF.H264.VideoAPI="视频的 API"
128
+AMF.H264.VideoAPI.Description="要用于编码的 API。"
129
+AMF.H264.VideoAdapter="视频适配器"
130
+AMF.H264.VideoAdapter.Description="哪种适配器用来编码."
131
+AMF.H264.OpenCL="OpenCL"
132
+AMF.H264.OpenCL.Description="编码器应该使用 OpenCL 提交单独的帧吗>"
133
 AMF.H264.View="查看模式"
134
 AMF.H264.View.Description="哪些属性应该是可见的. 当使用 '专家' 或者 '大师' 模式时, 您将不会得到支持."
135
 AMF.H264.View.Basic="基本"
136
 AMF.H264.View.Advanced="高级"
137
 AMF.H264.View.Expert="专家"
138
 AMF.H264.View.Master="主"
139
-AMF.H264.UnlockProperties="解锁属性"
140
-AMF.H264.UnlockProperties.Description="解锁给他们完整范围的某些属性, 而不是将他们局限到一定范围内."
141
 AMF.H264.Debug="调试"
142
 AMF.H264.Debug.Description="启用附加调试日志记录, 应该是启用的, 无论何时您需要此编码器的支持."
143
-AMF.Util.Default="默认"
144
-AMF.Util.Automatic="自动"
145
-AMF.Util.Manual="手动"
146
-AMF.Util.Toggle.Disabled="禁用"
147
-AMF.Util.Toggle.Enabled="启用"
148
+
149
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Resources/locale/zh-TW.ini -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/zh-TW.ini Changed
76
 
1
@@ -1,3 +1,8 @@
2
+AMF.Util.Default="預設"
3
+AMF.Util.Automatic="自動"
4
+AMF.Util.Manual="手動"
5
+AMF.Util.Toggle.Disabled="停用"
6
+AMF.Util.Toggle.Enabled="啟用"
7
 AMF.H264.Preset="預設"
8
 AMF.H264.Preset.ResetToDefaults="重設為預設值"
9
 AMF.H264.Preset.Recording="錄影"
10
@@ -19,11 +24,6 @@
11
 AMF.H264.Profile.Description="用於編碼的 H.264 設定:\n- 'Baseline' 有最廣泛的平台支援度,\n- 'Main' 較舊的裝置也支援 (如果目標是行動裝置,建議選此),\n- 'High' 當前主流裝置支援 (建議選此)。"
12
 AMF.H264.ProfileLevel="設定檔級別"
13
 AMF.H264.ProfileLevel.Description="用於編碼的 H.264 設定等級:\n- '\@AMF.Util.Automatic\@'根據給定的畫面播放速率以及尺寸計算最佳的設定等級,\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"
14
-AMF.H264.MaximumLTRFrames="長期參照訊框(LTR)最大數量"
15
-AMF.H264.MaximumLTRFrames.Description="當指定了長期參照訊框(LTR)最大數量時,編碼器將會停用 B-Picture。"
16
-AMF.H264.ScanType="掃描類型"
17
-AMF.H264.ScanType.Progressive="漸進式"
18
-AMF.H264.ScanType.Interlaced="交错式"
19
 AMF.H264.RateControlMethod="速率控制方法"
20
 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 延遲跟負載允許的情況下盡量接近目標位元速率,不足時使用較高的位元速率(建議用於錄影)。"
21
 AMF.H264.RateControlMethod.CQP="固定 QP (CQP)"
22
@@ -39,48 +39,36 @@
23
 AMF.H264.QP.Maximum="最大 QP 值"
24
 AMF.H264.QP.Maximum.Description="一個訊框中使用的最高 QP (量化參數) 值。"
25
 AMF.H264.QP.IFrame="I-訊框 QP"
26
-AMF.H264.QP.IFrame.Description="I-訊框使用的固定 QP (量化參數) 值。\nI-訊框 QP 應該要跟 P/B-訊框 QP 一樣或更高。"
27
 AMF.H264.QP.PFrame="P-訊框 QP"
28
-AMF.H264.QP.PFrame.Description="P-訊框使用的固定 QP (量化參數) 值。\nP-訊框 QP 應該要跟 B-訊框 QP 一樣或更高。"
29
 AMF.H264.QP.BFrame="B-訊框 QP"
30
 AMF.H264.QP.BFrame.Description="B-訊框使用的固定 QP (量化參數) 值。"
31
-AMF.H264.QP.BPictureDelta="B-Picture Delta QP"
32
-AMF.H264.QP.BPictureDelta.Description="最後一個非參考 B-Picture 所使用的 Delta QP。"
33
-AMF.H264.QP.ReferenceBPictureDelta="Reference B-Picture Delta QP"
34
-AMF.H264.QP.ReferenceBPictureDelta.Description="最後一個參考 B-Picture 所使用的 Delta QP。"
35
 AMF.H264.VBVBuffer="VBV(Video Buffering Verifier) 緩衝區"
36
 AMF.H264.VBVBuffer.Description="決定 VBV 緩衝區大小的方法:\n- '\@AMF.Util.Automatic\@' 根據嚴格性計算大小,\n- '\@AMF.Util.Manual\@' 允許使用者調整大小。\n 某些速率控制方法會使用 VBV (Video Buffering Verifier) 緩衝區讓整體的位元速率保持在給定的條件之內。"
37
 AMF.H264.VBVBuffer.Strictness="VBV 緩衝區嚴格性"
38
-AMF.H264.VBVBuffer.Strictness.Description="VBV 緩衝區嚴格程度,100% 表示幾乎跟目標位元速率一樣,0% 則不受限制。"
39
 AMF.H264.VBVBuffer.Size="VBV 緩衝區大小"
40
-AMF.H264.VBVBuffer.Size.Description="用於位元流量控制的 VBV 緩衝區大小。\n一個極小值將會得到近乎完美的位元速率結果,但是會有較大的效能消耗。"
41
 AMF.H264.VBVBuffer.Fullness="初始 VBV 緩衝區填充度"
42
 AMF.H264.VBVBuffer.Fullness.Description="VBV 緩衝區起始該多滿,將只影響編碼的起始。"
43
 AMF.H264.FillerData="填塞空白資料"
44
 AMF.H264.FillerData.Description="啟用填塞空白資料允許編碼器保持位元速率至少有目標位元速率,編碼器將會將不足的位元用空白訊息填滿"
45
 AMF.H264.FrameSkipping="省略訊框"
46
 AMF.H264.EnforceHRDCompatibility="與 HRD 相容"
47
-AMF.H264.BPicture.Pattern="B-Picture 模式"
48
-AMF.H264.BPicture.Reference="B-Picture 參照"
49
 AMF.H264.DeblockingFilter="去塊狀色斑濾鏡"
50
+AMF.H264.ScanType="掃描類型"
51
+AMF.H264.ScanType.Progressive="漸進式"
52
+AMF.H264.ScanType.Interlaced="交错式"
53
 AMF.H264.MotionEstimation="動態估算"
54
 AMF.H264.MotionEstimation.Description="動態估算讓編碼器藉由估算像素移動來減少位元速率。"
55
 AMF.H264.MotionEstimation.None="無"
56
 AMF.H264.MotionEstimation.Half="半像素"
57
 AMF.H264.MotionEstimation.Quarter="四分之一像素"
58
 AMF.H264.MotionEstimation.Both="半 & 四分之一像素"
59
+AMF.H264.MaximumLTRFrames="長期參照訊框(LTR)最大數量"
60
 AMF.H264.View="檢視模式"
61
 AMF.H264.View.Description="該顯示哪些屬性?\n使用'\@AMF.H264.View.Master\@'時將不提供任何的支援。"
62
 AMF.H264.View.Basic="基本"
63
 AMF.H264.View.Advanced="進階"
64
 AMF.H264.View.Expert="專家"
65
 AMF.H264.View.Master="上帝模式"
66
-AMF.H264.UnlockProperties="解除屬性值限制"
67
-AMF.H264.UnlockProperties.Description="允許一些屬性的數值範圍為全部可行的範圍,而非限定在一定的範圍內。"
68
 AMF.H264.Debug="除錯模式"
69
 AMF.H264.Debug.Description="啟用額外的除錯紀錄,當需要任何關於此編碼器的支援時皆應啟用。"
70
-AMF.Util.Default="預設"
71
-AMF.Util.Automatic="自動"
72
-AMF.Util.Manual="手動"
73
-AMF.Util.Toggle.Disabled="停用"
74
-AMF.Util.Toggle.Enabled="啟用"
75
+
76
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/amf-capabilities.cpp Added
383
 
1
@@ -0,0 +1,381 @@
2
+/*
3
+MIT License
4
+
5
+Copyright (c) 2016 Michael Fabian Dirks
6
+
7
+Permission is hereby granted, free of charge, to any person obtaining a copy
8
+of this software and associated documentation files (the "Software"), to deal
9
+in the Software without restriction, including without limitation the rights
10
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+copies of the Software, and to permit persons to whom the Software is
12
+furnished to do so, subject to the following conditions:
13
+
14
+The above copyright notice and this permission notice shall be included in all
15
+copies or substantial portions of the Software.
16
+
17
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+SOFTWARE.
24
+*/
25
+
26
+#pragma once
27
+
28
+//////////////////////////////////////////////////////////////////////////
29
+// Includes
30
+//////////////////////////////////////////////////////////////////////////
31
+#include <string>
32
+#include <sstream>
33
+
34
+#ifdef _WIN32
35
+#include <windows.h>
36
+#include <VersionHelpers.h>
37
+#endif
38
+
39
+#include "amf-capabilities.h"
40
+#include "api-d3d11.h"
41
+#include "api-d3d9.h"
42
+#include "misc-util.cpp"
43
+
44
+//////////////////////////////////////////////////////////////////////////
45
+// Code
46
+//////////////////////////////////////////////////////////////////////////
47
+
48
+Plugin::AMD::VCEDeviceCapabilities::VCEDeviceCapabilities() {
49
+   acceleration_type = amf::AMF_ACCEL_NOT_SUPPORTED;
50
+   maxProfile =
51
+       maxProfileLevel =
52
+       maxBitrate =
53
+       minReferenceFrames =
54
+       maxReferenceFrames =
55
+       maxTemporalLayers =
56
+       maxNumOfStreams =
57
+       maxNumOfHwInstances =
58
+       input.minWidth =
59
+       input.maxWidth =
60
+       input.minHeight =
61
+       input.maxHeight =
62
+       input.verticalAlignment =
63
+       output.minWidth =
64
+       output.maxWidth =
65
+       output.minHeight =
66
+       output.maxHeight =
67
+       output.verticalAlignment = 0;
68
+   supportsBFrames =
69
+       supportsFixedSliceMode =
70
+       input.supportsInterlaced =
71
+       output.supportsInterlaced = false;
72
+   input.formats.clear();
73
+   input.memoryTypes.clear();
74
+   output.formats.clear();
75
+   output.memoryTypes.clear();
76
+}
77
+
78
+std::shared_ptr<Plugin::AMD::VCECapabilities> Plugin::AMD::VCECapabilities::GetInstance() {
79
+   static std::shared_ptr<VCECapabilities> __instance = std::make_shared<VCECapabilities>();
80
+   static std::mutex __mutex;
81
+
82
+   const std::lock_guard<std::mutex> lock(__mutex);
83
+   return __instance;
84
+}
85
+
86
+void Plugin::AMD::VCECapabilities::ReportCapabilities(std::shared_ptr<Plugin::API::Base> api) {
87
+   auto inst = GetInstance();
88
+   auto adapters = api->EnumerateAdapters();
89
+   for (auto adapter : adapters) {
90
+       ReportAdapterCapabilities(api, adapter);
91
+   }
92
+}
93
+
94
+void Plugin::AMD::VCECapabilities::ReportAdapterCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter) {
95
+   auto inst = GetInstance();
96
+   VCEEncoderType types[] = {
97
+       VCEEncoderType_AVC,
98
+       VCEEncoderType_SVC,
99
+   };
100
+
101
+   AMF_LOG_INFO("Capabilities for Device '%s' on API %s:",
102
+       adapter.Name.c_str(),
103
+       api->GetName().c_str());
104
+
105
+   for (auto type : types) {
106
+       ReportAdapterTypeCapabilities(api, adapter, type);
107
+   }
108
+}
109
+
110
+void Plugin::AMD::VCECapabilities::ReportAdapterTypeCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter, VCEEncoderType type) {
111
+   auto inst = GetInstance();
112
+   auto caps = inst->GetAdapterCapabilities(api, adapter, type);
113
+
114
+   AMF_LOG_INFO("  %s (Acceleration: %s)",
115
+       (type == VCEEncoderType_AVC ? "AVC" : (type == VCEEncoderType_SVC ? "SVC" : (type == VCEEncoderType_HEVC ? "HEVC" : "Unknown"))),
116
+       (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")))
117
+   );
118
+
119
+   if (caps.acceleration_type == amf::AMF_ACCEL_NOT_SUPPORTED)
120
+       return;
121
+
122
+   AMF_LOG_INFO("    Limits");
123
+   AMF_LOG_INFO("      Profile: %s", Plugin::Utility::ProfileAsString((VCEProfile)caps.maxProfile));
124
+   AMF_LOG_INFO("      Profile Level: %ld.%ld", caps.maxProfileLevel / 10, caps.maxProfileLevel % 10);
125
+   AMF_LOG_INFO("      Bitrate: %ld", caps.maxBitrate);
126
+   AMF_LOG_INFO("      Reference Frames: %ld (min) - %ld (max)", caps.minReferenceFrames, caps.maxReferenceFrames);
127
+   if (type == VCEEncoderType_SVC)
128
+       AMF_LOG_INFO("      Temporal Layers: %ld", caps.maxTemporalLayers);
129
+   AMF_LOG_INFO("    Features");
130
+   AMF_LOG_INFO("      B-Frames: %s", caps.supportsBFrames ? "Supported" : "Not Supported");
131
+   AMF_LOG_INFO("      Fixed Slice Mode: %s", caps.supportsFixedSliceMode ? "Supported" : "Not Supported");
132
+   AMF_LOG_INFO("    Instancing");
133
+   AMF_LOG_INFO("      # of Streams: %ld", caps.maxNumOfStreams);
134
+   AMF_LOG_INFO("      # of Instances: %ld", caps.maxNumOfHwInstances);
135
+   AMF_LOG_INFO("    Input");
136
+   ReportAdapterTypeIOCapabilities(api, adapter, type, false);
137
+   AMF_LOG_INFO("    Output");
138
+   ReportAdapterTypeIOCapabilities(api, adapter, type, true);
139
+}
140
+
141
+void Plugin::AMD::VCECapabilities::ReportAdapterTypeIOCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter, VCEEncoderType type, bool output) {
142
+   auto amf = Plugin::AMD::AMF::GetInstance();
143
+
144
+   auto inst = GetInstance();
145
+   VCEDeviceCapabilities::IOCaps ioCaps = output
146
+       ? inst->GetAdapterCapabilities(api, adapter, type).output
147
+       : inst->GetAdapterCapabilities(api, adapter, type).input;
148
+   AMF_LOG_INFO("      Resolution: %ldx%ld - %ldx%ld",
149
+       ioCaps.minWidth, ioCaps.minHeight,
150
+       ioCaps.maxWidth, ioCaps.maxHeight);
151
+   AMF_LOG_INFO("      Vertical Alignment: %ld", ioCaps.verticalAlignment);
152
+   AMF_LOG_INFO("      Interlaced: %s", ioCaps.supportsInterlaced ? "Supported" : "Not Supported");
153
+   std::stringstream formatstr;
154
+   for (auto format : ioCaps.formats) {
155
+       std::vector<char> buf(1024);
156
+       wcstombs(buf.data(), amf->GetTrace()->SurfaceGetFormatName(format.first), 1024);
157
+       formatstr
158
+           << buf.data()
159
+           << (format.second ? " (Native)" : "")
160
+           << ", ";
161
+   }
162
+   AMF_LOG_INFO("      Formats: %s", formatstr.str().c_str());
163
+   std::stringstream memorystr;
164
+   for (auto memory : ioCaps.memoryTypes) {
165
+       std::vector<char> buf(1024);
166
+       wcstombs(buf.data(), amf->GetTrace()->GetMemoryTypeName(memory.first), 1024);
167
+       memorystr
168
+           << buf.data()
169
+           << (memory.second ? " (Native)" : "")
170
+           << ", ";
171
+   }
172
+   AMF_LOG_INFO("      Memory Types: %s", memorystr.str().c_str());
173
+}
174
+
175
+Plugin::AMD::VCECapabilities::VCECapabilities() {
176
+   this->Refresh();
177
+}
178
+
179
+Plugin::AMD::VCECapabilities::~VCECapabilities() {}
180
+
181
+static AMF_RESULT GetIOCapability(bool output, amf::AMFCapsPtr amfCaps, Plugin::AMD::VCEDeviceCapabilities::IOCaps* caps) {
182
+   AMF_RESULT res = AMF_OK;
183
+   amf::AMFIOCapsPtr amfIOCaps;
184
+   if (output)
185
+       res = amfCaps->GetOutputCaps(&amfIOCaps);
186
+   else
187
+       res = amfCaps->GetInputCaps(&amfIOCaps);
188
+   if (res != AMF_OK)
189
+       return res;
190
+
191
+   amfIOCaps->GetWidthRange(&(caps->minWidth), &(caps->maxWidth));
192
+   amfIOCaps->GetHeightRange(&(caps->minHeight), &(caps->maxHeight));
193
+   caps->supportsInterlaced = amfIOCaps->IsInterlacedSupported();
194
+   caps->verticalAlignment = amfIOCaps->GetVertAlign();
195
+
196
+   int32_t numFormats = amfIOCaps->GetNumOfFormats();
197
+   caps->formats.resize(numFormats);
198
+   for (int32_t formatIndex = 0; formatIndex < numFormats; formatIndex++) {
199
+       amf::AMF_SURFACE_FORMAT format = amf::AMF_SURFACE_UNKNOWN;
200
+       bool isNative = false;
201
+
202
+       amfIOCaps->GetFormatAt(formatIndex, &format, &isNative);
203
+       caps->formats[formatIndex].first = format;
204
+       caps->formats[formatIndex].second = isNative;
205
+   }
206
+
207
+   int32_t numMemoryTypes = amfIOCaps->GetNumOfMemoryTypes();
208
+   caps->memoryTypes.resize(numMemoryTypes);
209
+   for (int32_t memoryTypeIndex = 0; memoryTypeIndex < numMemoryTypes; memoryTypeIndex++) {
210
+       amf::AMF_MEMORY_TYPE type = amf::AMF_MEMORY_UNKNOWN;
211
+       bool isNative = false;
212
+
213
+       amfIOCaps->GetMemoryTypeAt(memoryTypeIndex, &type, &isNative);
214
+       caps->memoryTypes[memoryTypeIndex].first = type;
215
+       caps->memoryTypes[memoryTypeIndex].second = isNative;
216
+   }
217
+
218
+   return AMF_OK;
219
+}
220
+
221
+bool Plugin::AMD::VCECapabilities::Refresh() {
222
+   AMF_RESULT res;
223
+
224
+   auto amfInstance = AMD::AMF::GetInstance();
225
+   auto amfFactory = amfInstance->GetFactory();
226
+
227
+   auto APIs = Plugin::API::Base::EnumerateAPIs();
228
+   for (auto api : APIs) {
229
+       std::vector<Plugin::API::Adapter> adapters;
230
+       try {
231
+           adapters = api->EnumerateAdapters();
232
+       } catch (std::exception e) {
233
+           AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Unexpected exception while enumerating adapters for API '%s':", api->GetName());
234
+           AMF_LOG_ERROR("%s", e.what());
235
+           continue;
236
+       } catch (...) {
237
+           AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Unexpected critical exception while enumerating adapters for API '%s'.", api->GetName());
238
+           throw;
239
+       }
240
+
241
+       for (auto adapter : adapters) {
242
+           // Create AMF Instance
243
+           amf::AMFContextPtr amfContext;
244
+           if (amfFactory->CreateContext(&amfContext) != AMF_OK) {
245
+               AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> CreateContext failed for device '%s', error %ls (code %d).",
246
+                   adapter.Name.c_str(),
247
+                   amfInstance->GetTrace()->GetResultText(res),
248
+                   res);
249
+               continue;
250
+           }
251
+
252
+           void* apiInst = nullptr;
253
+           try {
254
+               apiInst = api->CreateInstanceOnAdapter(adapter);
255
+           } catch (std::exception e) {
256
+               AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Unexpected exception while testing adapter '%s' on API '%s':", adapter.Name, api->GetName());
257
+               AMF_LOG_ERROR("%s", e.what());
258
+               continue;
259
+           } catch (...) {
260
+               AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Unexpected critical exceptionwhile testing adapter '%s' on API '%s'.", adapter.Name, api->GetName());
261
+               throw;
262
+           }
263
+           switch (api->GetType()) {
264
+               case Plugin::API::APIType_Direct3D11:
265
+                   res = amfContext->InitDX11(api->GetContextFromInstance(apiInst));
266
+                   break;
267
+               case Plugin::API::APIType_Direct3D9:
268
+                   res = amfContext->InitDX9(api->GetContextFromInstance(apiInst));
269
+                   break;
270
+               case Plugin::API::APIType_OpenGL:
271
+                   res = amfContext->InitOpenGL(api->GetContextFromInstance(apiInst), nullptr, nullptr);
272
+                   break;
273
+               default:
274
+                   res = AMF_OK;
275
+                   break;
276
+           }
277
+           if (res != AMF_OK) {
278
+               AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Init failed for device '%s', error %ls (code %d).",
279
+                   adapter.Name.c_str(),
280
+                   amfInstance->GetTrace()->GetResultText(res),
281
+                   res);
282
+               continue;
283
+           }
284
+
285
+           VCEEncoderType types[] = {
286
+               VCEEncoderType_AVC,
287
+               VCEEncoderType_SVC
288
+           };
289
+           for (auto type : types) {
290
+               VCEDeviceCapabilities devCaps = VCEDeviceCapabilities();
291
+
292
+               amf::AMFComponentPtr amfComponent;
293
+               if (amfFactory->CreateComponent(amfContext,
294
+                   Plugin::Utility::VCEEncoderTypeAsAMF(type),
295
+                   &amfComponent) != AMF_OK) {
296
+                   AMF_LOG_ERROR("CreateComponent failed for device '%s' with codec '%s', error %ls (code %d).",
297
+                       adapter.Name.c_str(),
298
+                       Plugin::Utility::VCEEncoderTypeAsString(type),
299
+                       amfInstance->GetTrace()->GetResultText(res),
300
+                       res);
301
+                   continue;
302
+               }
303
+
304
+               amf::AMFCapsPtr amfCaps;
305
+               res = amfComponent->GetCaps(&amfCaps);
306
+               if (res != AMF_OK) {
307
+                   AMF_LOG_ERROR("GetCaps failed for device '%s' with codec '%s', error %ls (code %d).",
308
+                       adapter.Name.c_str(),
309
+                       Plugin::Utility::VCEEncoderTypeAsString(type),
310
+                       amfInstance->GetTrace()->GetResultText(res),
311
+                       res);
312
+                   amfComponent->Terminate();
313
+                   continue;
314
+               }
315
+
316
+               devCaps.acceleration_type = amfCaps->GetAccelerationType();
317
+               if (devCaps.acceleration_type != amf::AMF_ACCEL_NOT_SUPPORTED) {
318
+                   amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_MAX_BITRATE, &(devCaps.maxBitrate));
319
+                   amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_NUM_OF_STREAMS, &(devCaps.maxNumOfStreams));
320
+                   amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_MAX_PROFILE, &(devCaps.maxProfile));
321
+                   amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_MAX_LEVEL, &(devCaps.maxProfileLevel));
322
+                   amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_BFRAMES, &(devCaps.supportsBFrames));
323
+                   amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_MIN_REFERENCE_FRAMES, &(devCaps.minReferenceFrames));
324
+                   amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_MAX_REFERENCE_FRAMES, &(devCaps.maxReferenceFrames));
325
+                   amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_MAX_TEMPORAL_LAYERS, &(devCaps.maxTemporalLayers));
326
+                   amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_FIXED_SLICE_MODE, &(devCaps.supportsFixedSliceMode));
327
+                   amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_NUM_OF_HW_INSTANCES, &(devCaps.maxNumOfHwInstances));
328
+
329
+                   if (GetIOCapability(false, amfCaps, &(devCaps.input)) != AMF_OK)
330
+                       AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> GetInputCaps failed for device '%s' with codec '%ls', error %ls (code %d).",
331
+                           adapter.Name.c_str(),
332
+                           Plugin::Utility::VCEEncoderTypeAsString(type),
333
+                           amfInstance->GetTrace()->GetResultText(res), res);
334
+
335
+                   if (GetIOCapability(true, amfCaps, &(devCaps.output)) != AMF_OK)
336
+                       AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> GetOutputCaps failed capabilities for device '%s' with codec '%ls', error %ls (code %d).",
337
+                           adapter.Name.c_str(),
338
+                           Plugin::Utility::VCEEncoderTypeAsString(type),
339
+                           amfInstance->GetTrace()->GetResultText(res), res);
340
+               }
341
+
342
+               amfComponent->Terminate();
343
+
344
+               // Insert
345
+               capabilityMap.insert(std::make_pair(
346
+                   std::make_tuple(api->GetName(), adapter, type),
347
+                   devCaps)
348
+               );
349
+           }
350
+           api->DestroyInstance(apiInst);
351
+           amfContext->Terminate();
352
+       }
353
+   }
354
+   return true;
355
+}
356
+
357
+std::vector<std::pair<VCEEncoderType, VCEDeviceCapabilities>> Plugin::AMD::VCECapabilities::GetAllAdapterCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter) {
358
+   std::vector<std::pair<VCEEncoderType, VCEDeviceCapabilities>> caps;
359
+   for (auto kv : capabilityMap) {
360
+       auto apiName = std::get<0>(kv.first);
361
+       auto adapter = std::get<1>(kv.first);
362
+
363
+       if (apiName != api->GetName())
364
+           continue;
365
+       if (adapter != adapter)
366
+           continue;
367
+
368
+       auto type = std::get<2>(kv.first);
369
+       caps.push_back(std::make_pair(type, kv.second));
370
+   }
371
+   return caps;
372
+}
373
+
374
+Plugin::AMD::VCEDeviceCapabilities Plugin::AMD::VCECapabilities::GetAdapterCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter, VCEEncoderType type) {
375
+   auto key = std::make_tuple(api->GetName(), adapter, type);
376
+
377
+   if (capabilityMap.count(key) == 0)
378
+       return VCEDeviceCapabilities();
379
+
380
+   return capabilityMap.find(key)->second;
381
+}
382
+
383
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/amf-h264.cpp Added
2093
 
1
@@ -0,0 +1,2091 @@
2
+/*
3
+MIT License
4
+
5
+Copyright (c) 2016 Michael Fabian Dirks
6
+
7
+Permission is hereby granted, free of charge, to any person obtaining a copy
8
+of this software and associated documentation files (the "Software"), to deal
9
+in the Software without restriction, including without limitation the rights
10
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+copies of the Software, and to permit persons to whom the Software is
12
+furnished to do so, subject to the following conditions:
13
+
14
+The above copyright notice and this permission notice shall be included in all
15
+copies or substantial portions of the Software.
16
+
17
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+SOFTWARE.
24
+*/
25
+
26
+//////////////////////////////////////////////////////////////////////////
27
+// Includes
28
+//////////////////////////////////////////////////////////////////////////
29
+#include <chrono>
30
+
31
+#include "amf-capabilities.h"
32
+#include "amf-h264.h"
33
+#include "misc-util.cpp"
34
+#include "api-base.h"
35
+
36
+// AMF
37
+#include "components/VideoEncoderVCE.h"
38
+#include "components/VideoConverter.h"
39
+
40
+//////////////////////////////////////////////////////////////////////////
41
+// Code
42
+//////////////////////////////////////////////////////////////////////////
43
+
44
+// Logging and Exception Helpers
45
+static void FormatTextWithAMFError(std::vector<char>* buffer, const char* format, AMF_RESULT res) {
46
+   sprintf(buffer->data(), format, Plugin::AMD::AMF::GetInstance()->GetTrace()->GetResultText(res), res);
47
+}
48
+
49
+template<typename _T>
50
+static void FormatTextWithAMFError(std::vector<char>* buffer, const char* format, _T other, AMF_RESULT res) {
51
+   sprintf(buffer->data(), format, other, Plugin::AMD::AMF::GetInstance()->GetTrace()->GetResultText(res), res);
52
+}
53
+
54
+// Class
55
+#ifdef _DEBUG
56
+static void fastPrintVariant(const char* text, amf::AMFVariantStruct variant) {
57
+   std::vector<char> buf(1024);
58
+   switch (variant.type) {
59
+       case amf::AMF_VARIANT_EMPTY:
60
+           sprintf(buf.data(), "%s%s", text, "Empty");
61
+           break;
62
+       case amf::AMF_VARIANT_BOOL:
63
+           sprintf(buf.data(), "%s%s", text, variant.boolValue ? "true" : "false");
64
+           break;
65
+       case amf::AMF_VARIANT_INT64:
66
+           sprintf(buf.data(), "%s%lld", text, variant.int64Value);
67
+           break;
68
+       case amf::AMF_VARIANT_DOUBLE:
69
+           sprintf(buf.data(), "%s%f", text, variant.doubleValue);
70
+           break;
71
+       case amf::AMF_VARIANT_RECT:
72
+           sprintf(buf.data(), "%s[%ld,%ld,%ld,%ld]", text,
73
+               variant.rectValue.top, variant.rectValue.left,
74
+               variant.rectValue.bottom, variant.rectValue.right);
75
+           break;
76
+       case amf::AMF_VARIANT_SIZE:
77
+           sprintf(buf.data(), "%s%ldx%ld", text,
78
+               variant.sizeValue.width, variant.sizeValue.height);
79
+           break;
80
+       case amf::AMF_VARIANT_POINT:
81
+           sprintf(buf.data(), "%s[%ld,%ld]", text,
82
+               variant.pointValue.x, variant.pointValue.y);
83
+           break;
84
+       case amf::AMF_VARIANT_RATE:
85
+           sprintf(buf.data(), "%s%ld/%ld", text,
86
+               variant.rateValue.num, variant.rateValue.den);
87
+           break;
88
+       case amf::AMF_VARIANT_RATIO:
89
+           sprintf(buf.data(), "%s%ld:%ld", text,
90
+               variant.ratioValue.num, variant.ratioValue.den);
91
+           break;
92
+       case amf::AMF_VARIANT_COLOR:
93
+           sprintf(buf.data(), "%s(%d,%d,%d,%d)", text,
94
+               variant.colorValue.r,
95
+               variant.colorValue.g,
96
+               variant.colorValue.b,
97
+               variant.colorValue.a);
98
+           break;
99
+       case amf::AMF_VARIANT_STRING:
100
+           sprintf(buf.data(), "%s'%s'", text,
101
+               variant.stringValue);
102
+           break;
103
+       case amf::AMF_VARIANT_WSTRING:
104
+           sprintf(buf.data(), "%s'%ls'", text,
105
+               variant.wstringValue);
106
+           break;
107
+   }
108
+   AMF_LOG_INFO("%s", buf.data());
109
+};
110
+
111
+static void printDebugInfo(amf::AMFComponentPtr m_AMFEncoder) {
112
+   amf::AMFPropertyInfo* pInfo;
113
+   size_t propCount = m_AMFEncoder->GetPropertyCount();
114
+   AMF_LOG_INFO("-- Internal AMF Encoder Properties --");
115
+   for (size_t propIndex = 0; propIndex < propCount; propIndex++) {
116
+       static const char* typeToString[] = {
117
+           "Empty",
118
+           "Boolean",
119
+           "Int64",
120
+           "Double",
121
+           "Rect",
122
+           "Size",
123
+           "Point",
124
+           "Rate",
125
+           "Ratio",
126
+           "Color",
127
+           "String",
128
+           "WString",
129
+           "Interface"
130
+       };
131
+
132
+       AMF_RESULT res = m_AMFEncoder->GetPropertyInfo(propIndex, (const amf::AMFPropertyInfo**) &pInfo);
133
+       if (res != AMF_OK)
134
+           continue;
135
+       AMF_LOG_INFO(" [%ls] %ls (Type: %s, Index %d)",
136
+           pInfo->name, pInfo->desc, typeToString[pInfo->type], propIndex);
137
+       AMF_LOG_INFO("  Content Type: %d",
138
+           pInfo->contentType);
139
+       AMF_LOG_INFO("  Access: %s%s%s",
140
+           (pInfo->accessType & amf::AMF_PROPERTY_ACCESS_READ) ? "R" : "",
141
+           (pInfo->accessType & amf::AMF_PROPERTY_ACCESS_WRITE) ? "W" : "",
142
+           (pInfo->accessType & amf::AMF_PROPERTY_ACCESS_WRITE_RUNTIME) ? "X" : "");
143
+
144
+       AMF_LOG_INFO("  Values:");
145
+       amf::AMFVariantStruct curStruct = amf::AMFVariantStruct();
146
+       m_AMFEncoder->GetProperty(pInfo->name, &curStruct);
147
+       fastPrintVariant("    Current: ", curStruct);
148
+       fastPrintVariant("    Default: ", pInfo->defaultValue);
149
+       fastPrintVariant("    Minimum: ", pInfo->minValue);
150
+       fastPrintVariant("    Maximum: ", pInfo->maxValue);
151
+       if (pInfo->pEnumDescription) {
152
+           AMF_LOG_INFO("  Enumeration: ");
153
+           const amf::AMFEnumDescriptionEntry* pEnumEntry = pInfo->pEnumDescription;
154
+           while (pEnumEntry->name != nullptr) {
155
+               AMF_LOG_INFO("    %ls (%ld)",
156
+                   pEnumEntry->name,
157
+                   pEnumEntry->value);
158
+               pEnumEntry++;
159
+           }
160
+       }
161
+   }
162
+}
163
+#endif
164
+
165
+Plugin::AMD::VCEEncoder::VCEEncoder(
166
+   VCEEncoderType p_Type,
167
+   std::string p_VideoAPI,
168
+   uint64_t p_VideoAdapterId,
169
+   bool p_OpenCL,
170
+   VCEColorFormat p_SurfaceFormat/* = VCESurfaceFormat_NV12*/
171
+) {
172
+   #pragma region Assign Default Values
173
+   m_EncoderType = p_Type;
174
+   m_ColorFormat = p_SurfaceFormat;
175
+   m_OpenCL = p_OpenCL;
176
+   m_Flag_IsStarted = false;
177
+   m_Flag_FirstFrameReceived = false;
178
+   m_Flag_FirstFrameSubmitted = false;
179
+   m_FrameSize.first = 64; m_FrameSize.second = 64;
180
+   m_FrameRate.first = 30; m_FrameRate.second = 1;
181
+   m_FrameRateDivisor = ((double_t)m_FrameRate.first / (double_t)m_FrameRate.second);
182
+   m_FrameRateReverseDivisor = ((double_t)m_FrameRate.second / (double_t)m_FrameRate.first);
183
+   m_InputQueueLimit = (uint32_t)(m_FrameRateDivisor);
184
+   m_InputQueueLastSize = 0;
185
+   m_TimerPeriod = 1;
186
+   m_LastQueueWarnMessageTime = std::chrono::high_resolution_clock::time_point(std::chrono::high_resolution_clock::duration(0));
187
+   #pragma endregion Assign Default Values
188
+
189
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Initializing...");
190
+
191
+   AMF_RESULT res = AMF_OK;
192
+   // AMF
193
+   m_AMF = AMF::GetInstance();
194
+   m_AMFFactory = m_AMF->GetFactory();
195
+   /// Create an AMF context.
196
+   if (m_AMFFactory->CreateContext(&m_AMFContext) != AMF_OK)
197
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> CreateContext failed with error %ls (code %ld).", res);
198
+   /// Initialize to a specific API.
199
+   m_API = Plugin::API::Base::GetAPIByName(p_VideoAPI);
200
+   m_APIAdapter = m_API->GetAdapterById(p_VideoAdapterId & UINT_MAX, (p_VideoAdapterId >> 32) & UINT_MAX);
201
+   m_APIInstance = m_API->CreateInstanceOnAdapter(m_APIAdapter);
202
+   switch (m_API->GetType()) {
203
+       case Plugin::API::APIType_Direct3D11:
204
+           m_MemoryType = VCEMemoryType_DirectX11;
205
+           res = m_AMFContext->InitDX11(m_API->GetContextFromInstance(m_APIInstance));
206
+           break;
207
+       case Plugin::API::APIType_Direct3D9:
208
+           m_MemoryType = VCEMemoryType_DirectX9;
209
+           res = m_AMFContext->InitDX9(m_API->GetContextFromInstance(m_APIInstance));
210
+           break;
211
+       case Plugin::API::APIType_OpenGL:
212
+           m_MemoryType = VCEMemoryType_OpenGL;
213
+           res = m_AMFContext->InitOpenGL(m_API->GetContextFromInstance(m_APIInstance), GetDesktopWindow(), nullptr);
214
+           break;
215
+       case Plugin::API::APIType_Host:
216
+           m_MemoryType = VCEMemoryType_Host;
217
+           m_OpenCL = false;
218
+           break;
219
+   }
220
+   if (res != AMF_OK)
221
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Initializing Video API failed with error %ls (code %ld).", res);
222
+
223
+   /// Initialize OpenCL if user selected it.
224
+   if (m_OpenCL) {
225
+       res = m_AMFContext->InitOpenCL(nullptr);
226
+       if (res != AMF_OK)
227
+           ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> InitOpenCL failed with error %ls (code %ld).", res);
228
+       m_AMFContext->GetCompute(amf::AMF_MEMORY_OPENCL, &m_AMFCompute);
229
+   }
230
+
231
+   /// Create the AMF Encoder component.
232
+   if (m_AMFFactory->CreateComponent(m_AMFContext, Plugin::Utility::VCEEncoderTypeAsAMF(p_Type), &m_AMFEncoder) != AMF_OK)
233
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Creating a component object failed with error %ls (code %ld).", res);
234
+
235
+   /// Create the AMF Converter component.
236
+   if (m_AMFFactory->CreateComponent(m_AMFContext, AMFVideoConverter, &m_AMFConverter) != AMF_OK)
237
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Unable to create VideoConverter component, error %ls (code %ld).", res);
238
+   if (m_AMFConverter->SetProperty(AMF_VIDEO_CONVERTER_MEMORY_TYPE, Utility::MemoryTypeAsAMF(m_MemoryType)) != AMF_OK)
239
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Memory Type not supported by VideoConverter component, error %ls (code %ld).", res);
240
+   if (m_AMFConverter->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_FORMAT, Utility::SurfaceFormatAsAMF(m_ColorFormat)))
241
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Color Format not supported by VideoConverter component, error %ls (code %ld).", res);
242
+
243
+   #ifdef _DEBUG
244
+   printDebugInfo(m_AMFEncoder);
245
+   #endif
246
+
247
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Initialized.");
248
+}
249
+
250
+Plugin::AMD::VCEEncoder::~VCEEncoder() {
251
+   if (m_Flag_IsStarted)
252
+       Stop();
253
+
254
+   // AMF
255
+   if (m_AMFConverter)
256
+       m_AMFConverter->Terminate();
257
+   if (m_AMFEncoder)
258
+       m_AMFEncoder->Terminate();
259
+   if (m_AMFContext)
260
+       m_AMFContext->Terminate();
261
+   m_AMFConverter = nullptr;
262
+   m_AMFEncoder = nullptr;
263
+   m_AMFContext = nullptr;
264
+
265
+   // API
266
+   if (m_APIInstance)
267
+       m_API->DestroyInstance(m_APIInstance);
268
+   m_APIInstance = nullptr;
269
+   m_API = nullptr;
270
+}
271
+
272
+void Plugin::AMD::VCEEncoder::Start() {
273
+   // Set proper Timer resolution.
274
+   m_TimerPeriod = 1;
275
+   while (timeBeginPeriod(m_TimerPeriod) == TIMERR_NOCANDO) {
276
+       ++m_TimerPeriod;
277
+   }
278
+
279
+   // Create Encoder
280
+   AMF_RESULT res = m_AMFEncoder->Init(Utility::SurfaceFormatAsAMF(m_ColorFormat),
281
+       m_FrameSize.first, m_FrameSize.second);
282
+   if (res != AMF_OK)
283
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Encoder initialization failed with error %ls (code %ld).", res);
284
+
285
+   // Create Converter
286
+   m_AMFConverter->SetProperty(AMF_VIDEO_CONVERTER_COLOR_PROFILE, this->GetColorProfile());
287
+   if (m_AMFConverter->SetProperty(L"FullRangeColor", this->IsFullRangeColorEnabled()) != AMF_OK)
288
+       m_AMFConverter->SetProperty(L"NominalRange", this->IsFullRangeColorEnabled());
289
+
290
+   res = m_AMFConverter->Init(Utility::SurfaceFormatAsAMF(m_ColorFormat), m_FrameSize.first, m_FrameSize.second);
291
+   if (res != AMF_OK)
292
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Converter initialization failed with error %ls (code %ld).", res);
293
+
294
+   m_Flag_IsStarted = true;
295
+
296
+   // Threading
297
+   m_Input.thread = std::thread(&(Plugin::AMD::VCEEncoder::InputThreadMain), this);
298
+   m_Output.thread = std::thread(&(Plugin::AMD::VCEEncoder::OutputThreadMain), this);
299
+
300
+   #ifdef _DEBUG
301
+   printDebugInfo(m_AMFEncoder);
302
+   #endif
303
+}
304
+
305
+void Plugin::AMD::VCEEncoder::Restart() {
306
+   if (!m_Flag_IsStarted)
307
+       return;
308
+
309
+   std::unique_lock<std::mutex> ilock(m_Input.mutex);
310
+   std::unique_lock<std::mutex> olock(m_Output.mutex);
311
+
312
+   // Create Encoder
313
+   AMF_RESULT res = m_AMFEncoder->ReInit(m_FrameSize.first, m_FrameSize.second);
314
+   if (res != AMF_OK)
315
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Initialization failed with error %ls (code %ld).", res);
316
+}
317
+
318
+void Plugin::AMD::VCEEncoder::Stop() {
319
+   // Restore Timer precision.
320
+   if (m_TimerPeriod != 0) {
321
+       timeEndPeriod(m_TimerPeriod);
322
+   }
323
+
324
+   m_Flag_IsStarted = false;
325
+
326
+   // Threading
327
+   m_Output.condvar.notify_all();
328
+   #if defined _WIN32 || defined _WIN64
329
+   { // Windows: Force terminate Thread after 1 second of waiting.
330
+       std::thread::native_handle_type hnd = m_Output.thread.native_handle();
331
+
332
+       uint32_t res = WaitForSingleObject((HANDLE)hnd, 1000);
333
+       switch (res) {
334
+           case WAIT_OBJECT_0:
335
+               m_Output.thread.join();
336
+               break;
337
+           default:
338
+               m_Output.thread.detach();
339
+               TerminateThread((HANDLE)hnd, 0);
340
+               break;
341
+       }
342
+   }
343
+   #else
344
+   m_Output.thread.join();
345
+   #endif
346
+
347
+   m_Input.condvar.notify_all();
348
+   #if defined _WIN32 || defined _WIN64
349
+   { // Windows: Force terminate Thread after 1 second of waiting.
350
+       std::thread::native_handle_type hnd = m_Input.thread.native_handle();
351
+
352
+       uint32_t res = WaitForSingleObject((HANDLE)hnd, 1000);
353
+       switch (res) {
354
+           case WAIT_OBJECT_0:
355
+               m_Input.thread.join();
356
+               break;
357
+           default:
358
+               m_Input.thread.detach();
359
+               TerminateThread((HANDLE)hnd, 0);
360
+               break;
361
+       }
362
+   }
363
+   #else
364
+   m_Input.thread.join();
365
+   #endif
366
+
367
+   // Stop AMF Encoder
368
+   if (m_AMFEncoder) {
369
+       m_AMFEncoder->Drain();
370
+       m_AMFEncoder->Flush();
371
+   }
372
+
373
+   // Clear Queues, Data
374
+   std::queue<amf::AMFSurfacePtr>().swap(m_Input.queue);
375
+   std::queue<amf::AMFDataPtr>().swap(m_Output.queue);
376
+   m_PacketDataBuffer.clear();
377
+   m_ExtraDataBuffer.clear();
378
+   }
379
+
380
+bool Plugin::AMD::VCEEncoder::IsStarted() {
381
+   return m_Flag_IsStarted;
382
+}
383
+
384
+bool Plugin::AMD::VCEEncoder::SendInput(struct encoder_frame* frame) {
385
+   // Early-Exception if not encoding.
386
+   if (!m_Flag_IsStarted) {
387
+       const char* error = "<" __FUNCTION_NAME__ "> Attempted to send input while not running.";
388
+       AMF_LOG_ERROR("%s", error);
389
+       throw std::exception(error);
390
+   }
391
+
392
+   // Attempt to queue for 1 second (forces "Encoding overloaded" message to appear).
393
+   bool queueSuccessful = false;
394
+   auto queueStart = std::chrono::high_resolution_clock::now();
395
+   auto queueDuration = std::chrono::nanoseconds((uint64_t)floor(m_FrameRateReverseDivisor * 1000000));
396
+   size_t queueSize = m_InputQueueLimit;
397
+   do {
398
+       // Wake up submission thread.
399
+       m_Input.condvar.notify_all();
400
+
401
+       {
402
+           std::unique_lock<std::mutex> qlock(m_Input.queuemutex);
403
+           queueSize = m_Input.queue.size();
404
+       }
405
+
406
+       // Push into queue if it has room.
407
+       if (queueSize < m_InputQueueLimit) {
408
+           amf::AMFSurfacePtr pAMFSurface = CreateSurfaceFromFrame(frame);
409
+           if (!pAMFSurface) {
410
+               AMF_LOG_ERROR("Unable copy frame for submission, terminating...");
411
+               return false;
412
+           } else {
413
+               pAMFSurface->SetPts(frame->pts / m_FrameRate.second);
414
+               pAMFSurface->SetProperty(L"Frame", frame->pts);
415
+               pAMFSurface->SetDuration((uint64_t)ceil(m_FrameRateReverseDivisor * AMF_SECOND));
416
+           }
417
+
418
+           {
419
+               std::unique_lock<std::mutex> qlock(m_Input.queuemutex);
420
+               m_Input.queue.push(pAMFSurface);
421
+               queueSize++;
422
+           }
423
+           queueSuccessful = true;
424
+           break;
425
+       }
426
+
427
+       // Sleep
428
+       std::this_thread::sleep_for(queueDuration / 4);
429
+   } while ((queueSuccessful == false) && (std::chrono::high_resolution_clock::now() - queueStart <= queueDuration));
430
+
431
+   // Report status.
432
+   auto timedelta = std::chrono::high_resolution_clock::now() - m_LastQueueWarnMessageTime;
433
+   if (timedelta >= std::chrono::seconds(1)) { // Only show these messages once per second.
434
+       if (queueSuccessful) {
435
+           int32_t queueSizeDelta = ((int32_t)m_InputQueueLastSize - (int32_t)queueSize);
436
+
437
+           if (queueSizeDelta >= 5) {
438
+               AMF_LOG_INFO("GPU Encoder is catching up, queue is shrinking... (%ld,%+ld,%ld)",
439
+                   m_InputQueueLastSize,
440
+                   queueSizeDelta,
441
+                   queueSize);
442
+               m_InputQueueLastSize = queueSize;
443
+           } else if (queueSizeDelta <= -5) {
444
+               AMF_LOG_WARNING("GPU Encoder overloaded, queue is growing... (%ld,%+ld,%ld)",
445
+                   m_InputQueueLastSize, queueSizeDelta, queueSize);
446
+               m_InputQueueLastSize = queueSize;
447
+           }
448
+       } else {
449
+           AMF_LOG_ERROR("GPU Encoder overloaded, dropping frame instead...");
450
+       }
451
+       m_LastQueueWarnMessageTime = std::chrono::high_resolution_clock::now();
452
+   }
453
+
454
+   /// Signal Thread Wakeup
455
+   m_Input.condvar.notify_all();
456
+
457
+   // WORKAROUND: Block for at most 5 seconds until the first frame has been submitted.
458
+   if (!m_Flag_FirstFrameSubmitted) {
459
+       auto startsubmit = std::chrono::high_resolution_clock::now();
460
+       auto diff = std::chrono::high_resolution_clock::now() - startsubmit;
461
+       do {
462
+           diff = std::chrono::high_resolution_clock::now() - startsubmit;
463
+           std::this_thread::sleep_for(std::chrono::milliseconds(1));
464
+       } while ((diff <= std::chrono::seconds(5)) && !m_Flag_FirstFrameSubmitted);
465
+       if (!m_Flag_FirstFrameSubmitted)
466
+           throw std::exception("Unable to submit first frame, terminating...");
467
+       else {
468
+           uint64_t dtime = (uint64_t)diff.count();
469
+           AMF_LOG_INFO("First submission took %ld.%ld seconds.", dtime / 1000000000, dtime % 1000000000);
470
+       }
471
+   }
472
+
473
+   return true;
474
+}
475
+
476
+bool Plugin::AMD::VCEEncoder::GetOutput(struct encoder_packet* packet, bool* received_packet) {
477
+   // Early-Exception if not encoding.
478
+   if (!m_Flag_IsStarted) {
479
+       const char* error = "<" __FUNCTION_NAME__ "> Attempted to send input while not running.";
480
+       AMF_LOG_ERROR("%s", error);
481
+       throw std::exception(error);
482
+   }
483
+
484
+   // Signal Output Thread to wake up.
485
+   m_Output.condvar.notify_all();
486
+
487
+   // Dequeue a Packet
488
+   bool queueSuccessful = false;
489
+   auto queueStart = std::chrono::high_resolution_clock::now();
490
+   auto queueDuration = std::chrono::nanoseconds((uint64_t)floor(m_FrameRateReverseDivisor * 1000000));
491
+   do {
492
+       std::unique_lock<std::mutex> qlock(m_Output.queuemutex);
493
+       if (m_Output.queue.size() != 0)
494
+           queueSuccessful = true;
495
+
496
+       // Sleep
497
+       std::this_thread::sleep_for(queueDuration / 4);
498
+   } while ((queueSuccessful == false) && (std::chrono::high_resolution_clock::now() - queueStart <= queueDuration));
499
+   if (!queueSuccessful)
500
+       return true;
501
+
502
+   // We've got a DataPtr, let's use it.
503
+   {
504
+       amf::AMFDataPtr pAMFData;
505
+       {
506
+           std::unique_lock<std::mutex> qlock(m_Output.queuemutex);
507
+           pAMFData = m_Output.queue.front();
508
+           m_Output.queue.pop();
509
+       }
510
+       amf::AMFBufferPtr pAMFBuffer = amf::AMFBufferPtr(pAMFData);
511
+
512
+       // Assemble Packet
513
+       packet->type = OBS_ENCODER_VIDEO;
514
+       /// Data
515
+       packet->size = pAMFBuffer->GetSize();
516
+       if (m_PacketDataBuffer.size() < packet->size) {
517
+           size_t newBufferSize = (size_t)exp2(ceil(log2(packet->size)));
518
+           AMF_LOG_DEBUG("Packet Buffer was resized to %d byte from %d byte.", newBufferSize, m_PacketDataBuffer.size());
519
+           m_PacketDataBuffer.resize(newBufferSize);
520
+       }
521
+       packet->data = m_PacketDataBuffer.data();
522
+       std::memcpy(packet->data, pAMFBuffer->GetNative(), packet->size);
523
+       /// Timestamps
524
+       packet->dts = (pAMFData->GetPts() - 2) * m_FrameRate.second; // Offset by 2 to support B-Frames
525
+       pAMFBuffer->GetProperty(L"Frame", &packet->pts);
526
+       { /// Packet Priority & Keyframe
527
+           uint64_t pktType;
528
+           pAMFData->GetProperty(AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE, &pktType);
529
+
530
+           switch ((AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_ENUM)pktType) {
531
+               case AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR://
532
+                   packet->keyframe = true;                // IDR-Frames are Key-Frames that contain a lot of information.
533
+                   packet->priority = 3;                   // Highest priority, always continue streaming with these.
534
+                   //packet->drop_priority = 3;                // Dropped IDR-Frames can only be replaced by the next IDR-Frame.
535
+                   break;
536
+               case AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_I:  // I-Frames need only a previous I- or IDR-Frame.
537
+                   packet->priority = 2;                   // I- and IDR-Frames will most likely be present.
538
+               //  packet->drop_priority = 2;              // So we can continue with a I-Frame when streaming.
539
+               //  break;
540
+               case AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_P:  // P-Frames need either a previous P-, I- or IDR-Frame.
541
+                   packet->priority = 1;                   // We can safely assume that at least one of these is present.
542
+               //  packet->drop_priority = 1;              // So we can continue with a P-Frame when streaming.
543
+               //  break;
544
+               case AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_B:  // B-Frames need either a parent B-, P-, I- or IDR-Frame.
545
+                   packet->priority = 0;                   // We don't know if the last non-dropped frame was a B-Frame.
546
+               //  packet->drop_priority = 1;              // So require a P-Frame or better to continue streaming.
547
+               //  break;
548
+           }
549
+       }
550
+       *received_packet = true;
551
+
552
+       // Debug: Packet Information
553
+       std::vector<wchar_t> fileName(128);
554
+       mbstowcs(fileName.data(), __FILE__, fileName.size());
555
+       std::vector<wchar_t> functionName(128);
556
+       mbstowcs(functionName.data(), __FUNCTION__, functionName.size());
557
+       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);
558
+   }
559
+
560
+   return true;
561
+}
562
+
563
+bool Plugin::AMD::VCEEncoder::GetExtraData(uint8_t**& extra_data, size_t*& extra_data_size) {
564
+   if (!m_AMFContext || !m_AMFEncoder)
565
+       throw std::exception("<" __FUNCTION_NAME__ "> Called while not initialized.");
566
+
567
+   if (!m_Flag_IsStarted)
568
+       throw std::exception("<" __FUNCTION_NAME__ "> Called while not encoding.");
569
+
570
+   amf::AMFVariant var;
571
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_EXTRADATA, &var);
572
+   if (res == AMF_OK && var.type == amf::AMF_VARIANT_INTERFACE) {
573
+       amf::AMFBufferPtr buf(var.pInterface);
574
+
575
+       *extra_data_size = buf->GetSize();
576
+       m_ExtraDataBuffer.resize(*extra_data_size);
577
+       std::memcpy(m_ExtraDataBuffer.data(), buf->GetNative(), *extra_data_size);
578
+       *extra_data = m_ExtraDataBuffer.data();
579
+
580
+       return true;
581
+   }
582
+   return false;
583
+}
584
+
585
+void Plugin::AMD::VCEEncoder::GetVideoInfo(struct video_scale_info*& vsi) {
586
+   if (!m_AMFContext || !m_AMFEncoder)
587
+       throw std::exception("<" __FUNCTION_NAME__ "> Called while not initialized.");
588
+
589
+   if (!m_Flag_IsStarted)
590
+       throw std::exception("<" __FUNCTION_NAME__ "> Called while not encoding.");
591
+
592
+   switch (m_ColorFormat) {
593
+       // 4:2:0 Formats
594
+       case VCEColorFormat_NV12:
595
+           vsi->format = VIDEO_FORMAT_NV12;
596
+           break;
597
+       case VCEColorFormat_I420:
598
+           vsi->format = VIDEO_FORMAT_I420;
599
+           break;
600
+       // 4:2:2 Formats
601
+       case VCEColorFormat_YUY2:
602
+           vsi->format = VIDEO_FORMAT_YUY2;
603
+           break;
604
+       // Uncompressed
605
+       case VCEColorFormat_RGBA:
606
+           vsi->format = VIDEO_FORMAT_RGBA;
607
+           break;
608
+       case VCEColorFormat_BGRA:
609
+           vsi->format = VIDEO_FORMAT_BGRA;
610
+           break;
611
+       // Other
612
+       case VCEColorFormat_GRAY:
613
+           vsi->format = VIDEO_FORMAT_Y800;
614
+           break;
615
+   }
616
+
617
+   // AMF requires Partial Range for some reason.
618
+   if (this->IsFullRangeColorEnabled()) { // Only use Full range if actually enabled.
619
+       vsi->range = VIDEO_RANGE_FULL;
620
+   } else {
621
+       vsi->range = VIDEO_RANGE_PARTIAL;
622
+   }
623
+}
624
+
625
+void Plugin::AMD::VCEEncoder::InputThreadMain(Plugin::AMD::VCEEncoder* p_this) {
626
+   p_this->InputThreadLogic();
627
+}
628
+
629
+void Plugin::AMD::VCEEncoder::OutputThreadMain(Plugin::AMD::VCEEncoder* p_this) {
630
+   p_this->OutputThreadLogic();
631
+}
632
+
633
+void Plugin::AMD::VCEEncoder::InputThreadLogic() { // Thread Loop that handles Surface Submission
634
+   // Assign Thread Name
635
+   static const char* __threadName = "enc-amf Input Thread";
636
+   SetThreadName(__threadName);
637
+
638
+   // Core Loop
639
+   std::unique_lock<std::mutex> lock(m_Input.mutex);
640
+   uint32_t repeatSurfaceSubmission = 0;
641
+   do {
642
+       m_Input.condvar.wait(lock);
643
+
644
+       // Assign Thread Name
645
+       static const char* __threadName = "enc-amf Input Thread";
646
+       SetThreadName(__threadName);
647
+
648
+       // Skip to check if isStarted is false.
649
+       if (!m_Flag_IsStarted)
650
+           continue;
651
+
652
+       // Dequeue Surface
653
+       amf::AMFSurfacePtr surface;
654
+       {
655
+           std::unique_lock<std::mutex> qlock(m_Input.queuemutex);
656
+           if (m_Input.queue.size() == 0)
657
+               continue; // Queue is empty, 
658
+           surface = m_Input.queue.front();
659
+       }
660
+
661
+       /// Convert Frame
662
+       AMF_RESULT res;
663
+       amf::AMFDataPtr outbuf;
664
+
665
+       res = m_AMFConverter->SubmitInput(surface);
666
+       if (res != AMF_OK)
667
+           ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Unable to submit Frame to Converter, error %ls (code %ld).", res);
668
+       res = m_AMFConverter->QueryOutput(&outbuf);
669
+       if (res != AMF_OK)
670
+           ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Unable to retrieve Frame from Converter, error %ls (code %ld).", res);
671
+
672
+       /// Submit to AMF
673
+       res = m_AMFEncoder->SubmitInput(outbuf);
674
+       if (res == AMF_OK) {
675
+           m_Flag_FirstFrameSubmitted = true;
676
+
677
+           { // Remove Surface from Queue
678
+               std::unique_lock<std::mutex> qlock(m_Input.queuemutex);
679
+               m_Input.queue.pop();
680
+           }
681
+
682
+           // Reset AMF_INPUT_FULL retries.
683
+           repeatSurfaceSubmission = 0;
684
+
685
+           // Continue with next Surface.
686
+           m_Input.condvar.notify_all();
687
+       } else if (res == AMF_INPUT_FULL) {
688
+           m_Output.condvar.notify_all();
689
+           if (repeatSurfaceSubmission < 5) {
690
+               repeatSurfaceSubmission++;
691
+               m_Input.condvar.notify_all();
692
+           }
693
+       } else if (res == AMF_EOF) {
694
+           // This should never happen, but on the off-chance that it does, just straight up leave the loop.
695
+           break;
696
+       } else {
697
+           // Unknown, unexpected return code.
698
+           std::vector<char> msgBuf(128);
699
+           FormatTextWithAMFError(&msgBuf, "%ls (code %d)", Plugin::AMD::AMF::GetInstance()->GetTrace()->GetResultText(res), res);
700
+           AMF_LOG_WARNING("<" __FUNCTION_NAME__ "> SubmitInput failed with error %s.", msgBuf.data());
701
+       }
702
+
703
+       std::this_thread::sleep_for(std::chrono::milliseconds(m_TimerPeriod));
704
+   } while (m_Flag_IsStarted);
705
+}
706
+
707
+void Plugin::AMD::VCEEncoder::OutputThreadLogic() {    // Thread Loop that handles Querying
708
+   // Assign Thread Name
709
+   static const char* __threadName = "enc-amf Output Thread";
710
+   SetThreadName(__threadName);
711
+
712
+   // Core Loop
713
+   std::unique_lock<std::mutex> lock(m_Output.mutex);
714
+   do {
715
+       m_Output.condvar.wait(lock);
716
+
717
+       // Assign Thread Name
718
+       static const char* __threadName = "enc-amf Output Thread";
719
+       SetThreadName(__threadName);
720
+
721
+       // Skip to check if isStarted is false.
722
+       if (!m_Flag_IsStarted)
723
+           continue;
724
+
725
+       amf::AMFDataPtr pData = amf::AMFDataPtr();
726
+       AMF_RESULT res = m_AMFEncoder->QueryOutput(&pData);
727
+       if (res == AMF_OK) {
728
+           m_Flag_FirstFrameReceived = true;
729
+
730
+           { // Queue
731
+               std::unique_lock<std::mutex> qlock(m_Output.queuemutex);
732
+               m_Output.queue.push(pData);
733
+           }
734
+
735
+           // Continue querying until nothing is left.
736
+           m_Output.condvar.notify_all();
737
+       } else if (res == AMF_REPEAT) {
738
+           m_Input.condvar.notify_all();
739
+       } else if (res == AMF_EOF) {
740
+           // This should never happen, but on the off-chance that it does, just straight up leave the loop.
741
+           break;
742
+       } else {
743
+           // Unknown, unexpected return code.
744
+           std::vector<char> msgBuf(128);
745
+           FormatTextWithAMFError(&msgBuf, "%s (code %d)", res);
746
+           AMF_LOG_WARNING("<" __FUNCTION_NAME__ "> QueryOutput failed with error %s.", msgBuf.data());
747
+       }
748
+
749
+       std::this_thread::sleep_for(std::chrono::milliseconds(m_TimerPeriod));
750
+   } while (m_Flag_IsStarted);
751
+}
752
+
753
+inline amf::AMFSurfacePtr Plugin::AMD::VCEEncoder::CreateSurfaceFromFrame(struct encoder_frame*& frame) {
754
+   AMF_RESULT res = AMF_UNEXPECTED;
755
+   amf::AMFSurfacePtr pSurface = nullptr;
756
+   if (m_OpenCL) {
757
+       amf_size l_origin[] = { 0, 0, 0 };
758
+       amf_size l_size0[] = { m_FrameSize.first, m_FrameSize.second, 1 };
759
+       amf_size l_size1[] = { m_FrameSize.first >> 1, m_FrameSize.second >> 1, 1 };
760
+
761
+       res = m_AMFContext->AllocSurface(Utility::MemoryTypeAsAMF(m_MemoryType),
762
+           Utility::SurfaceFormatAsAMF(m_ColorFormat),
763
+           m_FrameSize.first, m_FrameSize.second, &pSurface);
764
+       if (res != AMF_OK) // Unable to create Surface
765
+           ThrowExceptionWithAMFError("AllocSurface failed with error %ls (code %d).", res);
766
+
767
+       amf::AMFComputeSyncPointPtr pSyncPoint;
768
+       m_AMFCompute->PutSyncPoint(&pSyncPoint);
769
+       pSurface->Convert(amf::AMF_MEMORY_OPENCL);
770
+       m_AMFCompute->CopyPlaneFromHost(frame->data[0], l_origin, l_size0, frame->linesize[0], pSurface->GetPlaneAt(0), false);
771
+       m_AMFCompute->CopyPlaneFromHost(frame->data[1], l_origin, l_size1, frame->linesize[1], pSurface->GetPlaneAt(1), false);
772
+       m_AMFCompute->FinishQueue();
773
+       pSurface->Convert(Utility::MemoryTypeAsAMF(m_MemoryType));
774
+       pSyncPoint->Wait();
775
+   } else {
776
+       res = m_AMFContext->AllocSurface(amf::AMF_MEMORY_HOST, Utility::SurfaceFormatAsAMF(m_ColorFormat),
777
+           m_FrameSize.first, m_FrameSize.second, &pSurface);
778
+       if (res != AMF_OK) // Unable to create Surface
779
+           ThrowExceptionWithAMFError("AllocSurface failed with error %ls (code %d).", res);
780
+
781
+       size_t planeCount = pSurface->GetPlanesCount();
782
+       #pragma loop(hint_parallel(2))
783
+       for (uint8_t i = 0; i < planeCount; i++) {
784
+           amf::AMFPlanePtr plane = pSurface->GetPlaneAt(i);
785
+           void* plane_nat = plane->GetNative();
786
+           int32_t height = plane->GetHeight();
787
+           int32_t hpitch = plane->GetHPitch();
788
+
789
+           for (int32_t py = 0; py < height; py++) {
790
+               int32_t plane_off = py * hpitch;
791
+               int32_t frame_off = py * frame->linesize[i];
792
+               std::memcpy(
793
+                   static_cast<void*>(static_cast<uint8_t*>(plane_nat) + plane_off),
794
+                   static_cast<void*>(frame->data[i] + frame_off), frame->linesize[i]);
795
+           }
796
+       }
797
+
798
+       // Convert to AMF native type.
799
+       pSurface->Convert(Utility::MemoryTypeAsAMF(m_MemoryType));
800
+   }
801
+
802
+   return pSurface;
803
+}
804
+
805
+//////////////////////////////////////////////////////////////////////////
806
+// AMF Properties
807
+//////////////////////////////////////////////////////////////////////////
808
+
809
+void Plugin::AMD::VCEEncoder::LogProperties() {
810
+   AMF_LOG_INFO("-- AMD Advanced Media Framework Encoder --");
811
+
812
+   // Initialization Properties
813
+   AMF_LOG_INFO("Initialization Properties: ");
814
+   AMF_LOG_INFO("  Type: %s", Utility::VCEEncoderTypeAsString(m_EncoderType));
815
+   AMF_LOG_INFO("  Video API: %s", Utility::MemoryTypeAsString(m_MemoryType));
816
+   if (m_MemoryType != VCEMemoryType_Host) {
817
+       AMF_LOG_INFO("  Video Adapter: %s", m_APIAdapter.Name.c_str());
818
+       AMF_LOG_INFO("  OpenCL: %s", m_OpenCL ? "Enabled" : "Disabled");
819
+   }
820
+   AMF_LOG_INFO("  Color Format: %s", Utility::SurfaceFormatAsString(m_ColorFormat));
821
+
822
+   // Startup Properties
823
+   AMF_LOG_INFO("Startup Properties: ");
824
+   AMF_LOG_INFO("  Usage: %s", Utility::UsageAsString(GetUsage()));
825
+   AMF_LOG_INFO("  Quality Preset: %s", Utility::QualityPresetAsString(GetQualityPreset()));
826
+   AMF_LOG_INFO("  Profile: %s %d.%d", Utility::ProfileAsString(GetProfile()), GetProfileLevel() / 10, this->GetProfileLevel() % 10);
827
+
828
+   // Frame Properties
829
+   AMF_LOG_INFO("Frame Properties: ");
830
+   try {
831
+       AMF_LOG_INFO("  Color Profile: %s", GetColorProfile() == VCEColorProfile_709 ? "709" : "601");
832
+   } catch (...) {
833
+       AMF_LOG_INFO("  Color Profile: N/A");
834
+   }
835
+   try {
836
+       AMF_LOG_INFO("  Color Range: %s", IsFullRangeColorEnabled() ? "Full" : "Partial");
837
+   } catch (...) {
838
+       AMF_LOG_INFO("  Color Range: N/A");
839
+   }
840
+   AMF_LOG_INFO("  Resolution: %dx%d", GetResolution().first, GetResolution().second);
841
+   AMF_LOG_INFO("  Frame Rate: %d/%d", GetFrameRate().first, GetFrameRate().second);
842
+   AMF_LOG_INFO("  Scan Type: %s", GetScanType() == VCEScanType_Progressive ? "Progressive" : "Interlaced");
843
+
844
+   // Rate Control Properties
845
+   AMF_LOG_INFO("Rate Control Properties: ");
846
+   AMF_LOG_INFO("  Method: %s", Utility::RateControlMethodAsString(GetRateControlMethod()));
847
+   AMF_LOG_INFO("  Bitrate: ");
848
+   AMF_LOG_INFO("    Target: %d bits", GetTargetBitrate());
849
+   AMF_LOG_INFO("    Peak: %d bits", GetPeakBitrate());
850
+   AMF_LOG_INFO("  Quantization Parameter: ");
851
+   AMF_LOG_INFO("    Minimum: %d", GetMinimumQP());
852
+   AMF_LOG_INFO("    Maximum: %d", GetMaximumQP());
853
+   AMF_LOG_INFO("    I-Frame: %d", GetIFrameQP());
854
+   AMF_LOG_INFO("    P-Frame: %d", GetPFrameQP());
855
+   if (VCECapabilities::GetInstance()->GetAdapterCapabilities(m_API, m_APIAdapter, VCEEncoderType_AVC).supportsBFrames) {
856
+       try { AMF_LOG_INFO("    B-Frame: %d", GetBFrameQP()); } catch (...) {}
857
+   } else {
858
+       AMF_LOG_INFO("    B-Frame: N/A");
859
+   }
860
+   AMF_LOG_INFO("  VBV Buffer: ");
861
+   AMF_LOG_INFO("    Size: %d bits", GetVBVBufferSize());
862
+   AMF_LOG_INFO("    Initial Fullness: %f%%", GetInitialVBVBufferFullness() * 100.0);
863
+   AMF_LOG_INFO("  Flags: ");
864
+   AMF_LOG_INFO("    Filler Data: %s", IsFillerDataEnabled() ? "Enabled" : "Disabled");
865
+   AMF_LOG_INFO("    Frame Skipping: %s", IsFrameSkippingEnabled() ? "Enabled" : "Disabled");
866
+   AMF_LOG_INFO("    Enforce HRD Restrictions: %s", IsEnforceHRDRestrictionsEnabled() ? "Enabled" : "Disabled");
867
+
868
+   // Picture Control Properties
869
+   AMF_LOG_INFO("Picture Control Properties: ");
870
+   AMF_LOG_INFO("  IDR Period: %d frames", GetIDRPeriod());
871
+   if (VCECapabilities::GetInstance()->GetAdapterCapabilities(m_API, m_APIAdapter, VCEEncoderType_AVC).supportsBFrames) {
872
+       AMF_LOG_INFO("  B-Frame Pattern: %d", GetBFramePattern());
873
+       try {
874
+           AMF_LOG_INFO("  B-Frame Delta QP: %d", GetBFrameDeltaQP());
875
+       } catch (...) {
876
+           AMF_LOG_INFO("  B-Frame Delta QP: N/A");
877
+       }
878
+       AMF_LOG_INFO("  B-Frame Reference: %s", IsBFrameReferenceEnabled() ? "Enabled" : "Disabled");
879
+       try {
880
+           AMF_LOG_INFO("  B-Frame Reference Delta QP: %d", GetBFrameReferenceDeltaQP());
881
+       } catch (...) {
882
+           AMF_LOG_INFO("  B-Frame Reference Delta QP: N/A");
883
+       }
884
+   } else {
885
+       AMF_LOG_INFO("  B-Frame Pattern: N/A");
886
+       AMF_LOG_INFO("  B-Frame Delta QP: N/A");
887
+       AMF_LOG_INFO("  B-Frame Reference: N/A");
888
+       AMF_LOG_INFO("  B-Frame Reference Delta QP: N/A");
889
+   }
890
+
891
+   AMF_LOG_INFO("Miscellaneous Properties: ");
892
+   AMF_LOG_INFO("  Deblocking Filter: %s", IsDeblockingFilterEnabled() ? "Enabled" : "Disabled");
893
+   AMF_LOG_INFO("  Motion Estimation: %s",
894
+       (this->IsHalfPixelMotionEstimationEnabled()
895
+           ? (this->IsQuarterPixelMotionEstimationEnabled()
896
+               ? "Half & Quarter Pixel"
897
+               : "Half Pixel")
898
+           : (this->IsQuarterPixelMotionEstimationEnabled()
899
+               ? "Quarter Pixel"
900
+               : "None")
901
+           )
902
+   );
903
+
904
+   AMF_LOG_INFO("Experimental Properties: ");
905
+   try { AMF_LOG_INFO("  Maximum MB/s: %d", GetMaxMBPerSec()); } catch (...) {}
906
+   try { AMF_LOG_INFO("  Coding Type: %s", Utility::CodingTypeAsString(GetCodingType())); } catch (...) {}
907
+   try { AMF_LOG_INFO("  Wait For Task: %s", IsWaitForTaskEnabled() ? "Enabled" : "Disabled"); } catch (...) {}
908
+   try { AMF_LOG_INFO("  Pre-Analyiss Pass: %s", IsPreAnalysisPassEnabled() ? "Enabled" : "Disabled"); } catch (...) {}
909
+   try { AMF_LOG_INFO("  VBAQ: %s", IsVBAQEnabled() ? "Enabled" : "Disabled"); } catch (...) {}
910
+   try { AMF_LOG_INFO("  Header Insertion Spacing: %d frames", GetHeaderInsertionSpacing()); } catch (...) {}
911
+   try { AMF_LOG_INFO("  Maximum Long-Term Reference Frames: %d", GetMaximumLongTermReferenceFrames()); } catch (...) {}
912
+   try { AMF_LOG_INFO("  Maximum Access Unit Size: %d bits", GetMaximumAccessUnitSize()); } catch (...) {}
913
+   try { AMF_LOG_INFO("  Maximum Reference Frames: %d", GetMaximumReferenceFrames()); } catch (...) {}
914
+   try { AMF_LOG_INFO("  Aspect Ratio: %d:%d", GetAspectRatio().first, this->GetAspectRatio().second); } catch (...) {}
915
+   try { AMF_LOG_INFO("  GOP Size: %d", GetGOPSize()) } catch (...) {}
916
+   try { AMF_LOG_INFO("  GOP Alignment: %s", IsGOPAlignementEnabled() ? "Enabled" : "Disabled") } catch (...) {}
917
+   try { AMF_LOG_INFO("  Intra-Refresh Macroblocks Pro Slot: %d", GetIntraRefreshMacroblocksPerSlot()) } catch (...) {}
918
+   try { AMF_LOG_INFO("  Intra-Refresh Number Of Stripes: %d", GetIntraRefreshNumberOfStripes()) } catch (...) {}
919
+   try { AMF_LOG_INFO("  Slices Per Frame: %d", GetSlicesPerFrame()); } catch (...) {}
920
+   try { AMF_LOG_INFO("  Slice Mode: %s", Utility::SliceModeAsString(GetSliceMode())); } catch (...) {}
921
+   try { AMF_LOG_INFO("  Maximum Slice Size: %d", GetMaximumSliceSize()); } catch (...) {}
922
+   try { AMF_LOG_INFO("  Slice Control Mode: %s", Utility::SliceControlModeAsString(GetSliceControlMode())); } catch (...) {}
923
+   try { AMF_LOG_INFO("  Slice Control Size: %d", GetSliceControlSize()); } catch (...) {}
924
+
925
+   Plugin::AMD::VCECapabilities::ReportAdapterCapabilities(m_API, m_APIAdapter);
926
+
927
+   #ifdef _DEBUG
928
+   printDebugInfo(m_AMFEncoder);
929
+   #endif
930
+
931
+   AMF_LOG_INFO("-- AMD Advanced Media Framework VCE Encoder --");
932
+}
933
+
934
+void Plugin::AMD::VCEEncoder::SetUsage(VCEUsage usage) {
935
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_USAGE,
936
+       (uint32_t)Utility::UsageAsAMF(usage));
937
+   if (res != AMF_OK) {
938
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).",
939
+           res, Utility::UsageAsString(usage));
940
+   }
941
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", Utility::UsageAsString(usage));
942
+}
943
+
944
+Plugin::AMD::VCEUsage Plugin::AMD::VCEEncoder::GetUsage() {
945
+   uint32_t usage;
946
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_USAGE, &usage);
947
+   if (res != AMF_OK) {
948
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
949
+   }
950
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.",
951
+       Utility::UsageAsString(Utility::UsageFromAMF(usage)));
952
+   return Utility::UsageFromAMF(usage);
953
+}
954
+
955
+void Plugin::AMD::VCEEncoder::SetQualityPreset(VCEQualityPreset preset) {
956
+   static AMF_VIDEO_ENCODER_QUALITY_PRESET_ENUM CustomToAMF[] = {
957
+       AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED,
958
+       AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED,
959
+       AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY,
960
+   };
961
+   static char* CustomToName[] = {
962
+       "Speed",
963
+       "Balanced",
964
+       "Quality",
965
+   };
966
+
967
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_QUALITY_PRESET, (uint32_t)CustomToAMF[preset]);
968
+   if (res != AMF_OK) {
969
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, CustomToName[preset]);
970
+   }
971
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", CustomToName[preset]);
972
+}
973
+
974
+Plugin::AMD::VCEQualityPreset Plugin::AMD::VCEEncoder::GetQualityPreset() {
975
+   static VCEQualityPreset AMFToCustom[] = {
976
+       VCEQualityPreset_Balanced,
977
+       VCEQualityPreset_Speed,
978
+       VCEQualityPreset_Quality,
979
+   };
980
+   static char* CustomToName[] = {
981
+       "Speed",
982
+       "Balanced",
983
+       "Quality",
984
+   };
985
+
986
+   uint32_t preset;
987
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_QUALITY_PRESET, &preset);
988
+   if (res != AMF_OK) {
989
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
990
+   }
991
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", CustomToName[AMFToCustom[preset]]);
992
+   return AMFToCustom[preset];
993
+}
994
+
995
+void Plugin::AMD::VCEEncoder::SetProfile(VCEProfile profile) {
996
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_PROFILE, (uint32_t)profile);
997
+   if (res != AMF_OK) {
998
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, Utility::ProfileAsString(profile));
999
+   }
1000
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", Utility::ProfileAsString(profile));
1001
+}
1002
+
1003
+Plugin::AMD::VCEProfile Plugin::AMD::VCEEncoder::GetProfile() {
1004
+   uint32_t profile;
1005
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_PROFILE, &profile);
1006
+   if (res != AMF_OK) {
1007
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1008
+   }
1009
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", Utility::ProfileAsString((VCEProfile)profile));
1010
+   return (VCEProfile)profile;
1011
+}
1012
+
1013
+void Plugin::AMD::VCEEncoder::SetProfileLevel(VCEProfileLevel level) {
1014
+   // Automatic Detection
1015
+   if (level == VCEProfileLevel_Automatic) {
1016
+       auto frameSize = this->GetResolution();
1017
+       auto frameRate = this->GetFrameRate();
1018
+       level = Plugin::Utility::GetMinimumProfileLevel(frameSize, frameRate);
1019
+   }
1020
+
1021
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_PROFILE_LEVEL, (uint32_t)level);
1022
+   if (res != AMF_OK) {
1023
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, level);
1024
+   }
1025
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", level);
1026
+}
1027
+
1028
+Plugin::AMD::VCEProfileLevel Plugin::AMD::VCEEncoder::GetProfileLevel() {
1029
+   uint32_t profileLevel;
1030
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_PROFILE_LEVEL, &profileLevel);
1031
+   if (res != AMF_OK) {
1032
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1033
+   }
1034
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", profileLevel);
1035
+   return (VCEProfileLevel)(profileLevel);
1036
+}
1037
+
1038
+void Plugin::AMD::VCEEncoder::SetColorProfile(VCEColorProfile profile) {
1039
+   AMF_VIDEO_CONVERTER_COLOR_PROFILE_ENUM pluginToAMF[] = {
1040
+       AMF_VIDEO_CONVERTER_COLOR_PROFILE_601,
1041
+       AMF_VIDEO_CONVERTER_COLOR_PROFILE_709,
1042
+       AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020,
1043
+   };
1044
+   const char* pluginToString[] = {
1045
+       "601",
1046
+       "709",
1047
+       "2020",
1048
+   };
1049
+
1050
+   AMF_RESULT res = m_AMFConverter->SetProperty(AMF_VIDEO_CONVERTER_COLOR_PROFILE,
1051
+       pluginToAMF[profile]);
1052
+   if (res != AMF_OK)
1053
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Unable to set Color Profile, error %ls (code %ld).", res);
1054
+   m_ColorProfile = profile;
1055
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", pluginToString[profile]);
1056
+}
1057
+
1058
+Plugin::AMD::VCEColorProfile Plugin::AMD::VCEEncoder::GetColorProfile() {
1059
+   return m_ColorProfile;
1060
+}
1061
+
1062
+void Plugin::AMD::VCEEncoder::SetFullRangeColorEnabled(bool enabled) {
1063
+   // Info from Mikhail:
1064
+   // - Name may change in the future
1065
+   // - Use GetProperty or GetPropertyDescription to test for older or newer drivers.
1066
+   const wchar_t* names[] = {
1067
+       L"FullRangeColor", // 16.12.1
1068
+       L"NominalRange", // 16.11.5 and below.
1069
+   };
1070
+
1071
+   bool enabledTest;
1072
+   AMF_RESULT res = AMF_INVALID_ARG;
1073
+   for (size_t i = 0; i < _countof(names); i++) {
1074
+       if (m_AMFEncoder->GetProperty(names[i], &enabledTest) == AMF_OK) {
1075
+           m_AMFConverter->SetProperty(names[i], enabled);
1076
+           res = m_AMFEncoder->SetProperty(names[i], enabled);
1077
+           break;
1078
+       }
1079
+   }
1080
+   if (res != AMF_OK)
1081
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1082
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1083
+}
1084
+
1085
+bool Plugin::AMD::VCEEncoder::IsFullRangeColorEnabled() {
1086
+   // Info from Mikhail:
1087
+   // - Name may change in the future
1088
+   // - Use GetProperty or GetPropertyDescription to test for older or newer drivers.
1089
+   const wchar_t* names[] = {
1090
+       L"FullRangeColor", // 16.12.1
1091
+       L"NominalRange", // 16.11.5 and below.
1092
+   };
1093
+
1094
+   bool enabled;
1095
+   AMF_RESULT res = AMF_INVALID_ARG;
1096
+   for (size_t i = 0; i < _countof(names); i++) {
1097
+       res = m_AMFEncoder->GetProperty(names[i], &enabled);
1098
+       if (res == AMF_OK) {
1099
+           break;
1100
+       }
1101
+   }
1102
+   if (res != AMF_OK)
1103
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1104
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1105
+   return enabled;
1106
+}
1107
+
1108
+void Plugin::AMD::VCEEncoder::SetResolution(uint32_t width, uint32_t height) {
1109
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_FRAMESIZE, ::AMFConstructSize(width, height));
1110
+   if (res != AMF_OK) {
1111
+       std::vector<char> msgBuf(128);
1112
+       sprintf(msgBuf.data(), "%dx%d", width, height);
1113
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, msgBuf.data());
1114
+   }
1115
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %dx%d.", width, height);
1116
+   m_FrameSize.first = width;
1117
+   m_FrameSize.second = height;
1118
+
1119
+   if (this->GetProfileLevel() == VCEProfileLevel_Automatic)
1120
+       this->SetProfileLevel(VCEProfileLevel_Automatic);
1121
+}
1122
+
1123
+std::pair<uint32_t, uint32_t> Plugin::AMD::VCEEncoder::GetResolution() {
1124
+   AMFSize frameSize;
1125
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_FRAMESIZE, &frameSize);
1126
+   if (res != AMF_OK) {
1127
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1128
+   }
1129
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %dx%d.", frameSize.width, frameSize.height);
1130
+   m_FrameSize.first = frameSize.width;
1131
+   m_FrameSize.second = frameSize.height;
1132
+
1133
+   if (this->GetProfileLevel() == VCEProfileLevel_Automatic)
1134
+       this->SetProfileLevel(VCEProfileLevel_Automatic);
1135
+
1136
+   return std::pair<uint32_t, uint32_t>(m_FrameSize);
1137
+}
1138
+
1139
+void Plugin::AMD::VCEEncoder::SetFrameRate(uint32_t num, uint32_t den) {
1140
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_FRAMERATE, ::AMFConstructRate(num, den));
1141
+   if (res != AMF_OK) {
1142
+       std::vector<char> msgBuf;
1143
+       sprintf(msgBuf.data(), "%d/%d", num, den);
1144
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, msgBuf.data());
1145
+   }
1146
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d/%d.", num, den);
1147
+   m_FrameRate.first = num;
1148
+   m_FrameRate.second = den;
1149
+   m_FrameRateDivisor = (double_t)m_FrameRate.first / (double_t)m_FrameRate.second;
1150
+   m_FrameRateReverseDivisor = ((double_t)m_FrameRate.second / (double_t)m_FrameRate.first);
1151
+   m_InputQueueLimit = (uint32_t)ceil(m_FrameRateDivisor);
1152
+
1153
+   if (this->GetProfileLevel() == VCEProfileLevel_Automatic)
1154
+       this->SetProfileLevel(VCEProfileLevel_Automatic);
1155
+}
1156
+
1157
+std::pair<uint32_t, uint32_t> Plugin::AMD::VCEEncoder::GetFrameRate() {
1158
+   AMFRate frameRate;
1159
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_FRAMERATE, &frameRate);
1160
+   if (res != AMF_OK) {
1161
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1162
+   }
1163
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d/%d.", frameRate.num, frameRate.den);
1164
+   m_FrameRate.first = frameRate.num;
1165
+   m_FrameRate.second = frameRate.den;
1166
+   m_FrameRateDivisor = (double_t)frameRate.num / (double_t)frameRate.den;
1167
+   m_InputQueueLimit = (uint32_t)ceil(m_FrameRateDivisor);
1168
+
1169
+   if (this->GetProfileLevel() == VCEProfileLevel_Automatic)
1170
+       this->SetProfileLevel(VCEProfileLevel_Automatic);
1171
+
1172
+   return std::pair<uint32_t, uint32_t>(m_FrameRate);
1173
+}
1174
+
1175
+void Plugin::AMD::VCEEncoder::SetScanType(VCEScanType scanType) {
1176
+   static AMF_VIDEO_ENCODER_SCANTYPE_ENUM CustomToAMF[] = {
1177
+       AMF_VIDEO_ENCODER_SCANTYPE_PROGRESSIVE,
1178
+       AMF_VIDEO_ENCODER_SCANTYPE_INTERLACED,
1179
+   };
1180
+   static char* CustomToName[] = {
1181
+       "Progressive",
1182
+       "Interlaced",
1183
+   };
1184
+
1185
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_SCANTYPE, (uint32_t)CustomToAMF[scanType]);
1186
+   if (res != AMF_OK) {
1187
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, CustomToName[scanType]);
1188
+   }
1189
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", CustomToName[scanType]);
1190
+}
1191
+
1192
+Plugin::AMD::VCEScanType Plugin::AMD::VCEEncoder::GetScanType() {
1193
+   static char* CustomToName[] = {
1194
+       "Progressive",
1195
+       "Interlaced",
1196
+   };
1197
+
1198
+   uint32_t scanType;
1199
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_SCANTYPE, &scanType);
1200
+   if (res != AMF_OK) {
1201
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1202
+   }
1203
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", CustomToName[scanType]);
1204
+   return (Plugin::AMD::VCEScanType)scanType;
1205
+}
1206
+
1207
+void Plugin::AMD::VCEEncoder::SetRateControlMethod(VCERateControlMethod method) {
1208
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD,
1209
+       (uint64_t)Utility::RateControlMethodAsAMF(method));
1210
+   if (res != AMF_OK) {
1211
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).",
1212
+           res, Utility::RateControlMethodAsString(method));
1213
+   }
1214
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.",
1215
+       Utility::RateControlMethodAsString(method));
1216
+}
1217
+
1218
+Plugin::AMD::VCERateControlMethod Plugin::AMD::VCEEncoder::GetRateControlMethod() {
1219
+   uint32_t method;
1220
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD, &method);
1221
+   if (res != AMF_OK) {
1222
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1223
+   }
1224
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.",
1225
+       Utility::RateControlMethodAsString(Utility::RateControlMethodFromAMF(method)));
1226
+   return Utility::RateControlMethodFromAMF(method);
1227
+}
1228
+
1229
+void Plugin::AMD::VCEEncoder::SetTargetBitrate(uint32_t bitrate) {
1230
+   // Clamp Value
1231
+   bitrate = clamp(bitrate, 10000,
1232
+       Plugin::AMD::VCECapabilities::GetInstance()->GetAdapterCapabilities(m_API, m_APIAdapter, VCEEncoderType_AVC).maxBitrate);
1233
+
1234
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_TARGET_BITRATE, bitrate);
1235
+   if (res != AMF_OK) {
1236
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d bits failed with error %ls (code %d).", res, bitrate);
1237
+   }
1238
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d bits.", bitrate);
1239
+}
1240
+
1241
+uint32_t Plugin::AMD::VCEEncoder::GetTargetBitrate() {
1242
+   uint32_t bitrate;
1243
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_TARGET_BITRATE, &bitrate);
1244
+   if (res != AMF_OK) {
1245
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1246
+   }
1247
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d bits.", bitrate);
1248
+   return bitrate;
1249
+}
1250
+
1251
+void Plugin::AMD::VCEEncoder::SetPeakBitrate(uint32_t bitrate) {
1252
+   // Clamp Value
1253
+   bitrate = clamp(bitrate, 10000,
1254
+       Plugin::AMD::VCECapabilities::GetInstance()->GetAdapterCapabilities(m_API, m_APIAdapter, VCEEncoderType_AVC).maxBitrate);
1255
+
1256
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_PEAK_BITRATE, (uint32_t)bitrate);
1257
+   if (res != AMF_OK) {
1258
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d bits failed with error %ls (code %d).", res, bitrate);
1259
+   }
1260
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d bits.", bitrate);
1261
+}
1262
+
1263
+uint32_t Plugin::AMD::VCEEncoder::GetPeakBitrate() {
1264
+   uint32_t bitrate;
1265
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_PEAK_BITRATE, &bitrate);
1266
+   if (res != AMF_OK) {
1267
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1268
+   }
1269
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d bits.", bitrate);
1270
+   return bitrate;
1271
+}
1272
+
1273
+void Plugin::AMD::VCEEncoder::SetMinimumQP(uint8_t qp) {
1274
+   // Clamp Value
1275
+   qp = clamp(qp, 0, 51);
1276
+
1277
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_MIN_QP, (uint32_t)qp);
1278
+   if (res != AMF_OK) {
1279
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, qp);
1280
+   }
1281
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
1282
+}
1283
+
1284
+uint8_t Plugin::AMD::VCEEncoder::GetMinimumQP() {
1285
+   uint32_t qp;
1286
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MIN_QP, &qp);
1287
+   if (res != AMF_OK) {
1288
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1289
+   }
1290
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", qp);
1291
+   return (uint8_t)qp;
1292
+}
1293
+
1294
+void Plugin::AMD::VCEEncoder::SetMaximumQP(uint8_t qp) {
1295
+   // Clamp Value
1296
+   qp = clamp(qp, 0, 51);
1297
+
1298
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_MAX_QP, (uint32_t)qp);
1299
+   if (res != AMF_OK) {
1300
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, qp);
1301
+   }
1302
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
1303
+}
1304
+
1305
+uint8_t Plugin::AMD::VCEEncoder::GetMaximumQP() {
1306
+   uint32_t qp;
1307
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MAX_QP, &qp);
1308
+   if (res != AMF_OK) {
1309
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1310
+   }
1311
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", qp);
1312
+   return (uint8_t)qp;
1313
+}
1314
+
1315
+void Plugin::AMD::VCEEncoder::SetIFrameQP(uint8_t qp) {
1316
+   // Clamp Value
1317
+   qp = clamp(qp, 0, 51);
1318
+
1319
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_QP_I, (uint32_t)qp);
1320
+   if (res != AMF_OK) {
1321
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, qp);
1322
+   }
1323
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
1324
+}
1325
+
1326
+uint8_t Plugin::AMD::VCEEncoder::GetIFrameQP() {
1327
+   uint32_t qp;
1328
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_QP_I, &qp);
1329
+   if (res != AMF_OK) {
1330
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1331
+   }
1332
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", qp);
1333
+   return (uint8_t)qp;
1334
+}
1335
+
1336
+void Plugin::AMD::VCEEncoder::SetPFrameQP(uint8_t qp) {
1337
+   // Clamp Value
1338
+   qp = clamp(qp, 0, 51);
1339
+
1340
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_QP_P, (uint32_t)qp);
1341
+   if (res != AMF_OK) {
1342
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, qp);
1343
+   }
1344
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
1345
+}
1346
+
1347
+uint8_t Plugin::AMD::VCEEncoder::GetPFrameQP() {
1348
+   uint32_t qp;
1349
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_QP_P, &qp);
1350
+   if (res != AMF_OK) {
1351
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1352
+   }
1353
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", qp);
1354
+   return (uint8_t)qp;
1355
+}
1356
+
1357
+void Plugin::AMD::VCEEncoder::SetBFrameQP(uint8_t qp) {
1358
+   // Clamp Value
1359
+   qp = clamp(qp, 0, 51);
1360
+
1361
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_QP_B, (uint32_t)qp);
1362
+   if (res != AMF_OK) {
1363
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, qp);
1364
+   }
1365
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
1366
+}
1367
+
1368
+uint8_t Plugin::AMD::VCEEncoder::GetBFrameQP() {
1369
+   uint32_t qp;
1370
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_QP_B, &qp);
1371
+   if (res != AMF_OK) {
1372
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1373
+   }
1374
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", qp);
1375
+   return (uint8_t)qp;
1376
+}
1377
+
1378
+void Plugin::AMD::VCEEncoder::SetVBVBufferSize(uint32_t size) {
1379
+   // Clamp Value
1380
+   size = clamp(size, 1000, 100000000); // 1kbit to 100mbit.
1381
+
1382
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_VBV_BUFFER_SIZE, (uint32_t)size);
1383
+   if (res != AMF_OK) {
1384
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d bits failed with error %ls (code %d).", res, size);
1385
+   }
1386
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d bits.", size);
1387
+}
1388
+
1389
+void Plugin::AMD::VCEEncoder::SetVBVBufferAutomatic(double_t strictness) {
1390
+   uint32_t strictBitrate = 1000, looseBitrate = 100000000;
1391
+
1392
+   // Strict VBV Buffer Size = Bitrate / FPS
1393
+   // Loose VBV Buffer Size = Bitrate
1394
+
1395
+   switch (this->GetRateControlMethod()) {
1396
+       case VCERateControlMethod_ConstantBitrate:
1397
+       case VCERateControlMethod_VariableBitrate_LatencyConstrained:
1398
+           looseBitrate = this->GetTargetBitrate();
1399
+           break;
1400
+       case VCERateControlMethod_VariableBitrate_PeakConstrained:
1401
+           looseBitrate = max(this->GetTargetBitrate(), this->GetPeakBitrate());
1402
+           break;
1403
+       case VCERateControlMethod_ConstantQP:
1404
+           // When using Constant QP, one will have to pick a QP that is decent
1405
+           //  in both quality and bitrate. We can easily calculate both the QP
1406
+           //  required for an average bitrate and the average bitrate itself 
1407
+           //  with these formulas:
1408
+           // BITRATE = ((1 - (QP / 51)) ^ 2) * ((Width * Height) * 1.5 * (FPSNumerator / FPSDenumerator))
1409
+           // QP = (1 - sqrt(BITRATE / ((Width * Height) * 1.5 * (FPSNumerator / FPSDenumerator)))) * 51
1410
+
1411
+           auto frameSize = this->GetResolution();
1412
+           auto frameRate = this->GetFrameRate();
1413
+
1414
+           double_t bitrate = frameSize.first * frameSize.second;
1415
+           switch (this->m_ColorFormat) {
1416
+               case VCEColorFormat_NV12:
1417
+               case VCEColorFormat_I420:
1418
+                   bitrate *= 1.5;
1419
+                   break;
1420
+               case VCEColorFormat_YUY2:
1421
+                   bitrate *= 4;
1422
+                   break;
1423
+               case VCEColorFormat_BGRA:
1424
+               case VCEColorFormat_RGBA:
1425
+                   bitrate *= 3;
1426
+                   break;
1427
+               case VCEColorFormat_GRAY:
1428
+                   bitrate *= 1;
1429
+                   break;
1430
+           }
1431
+           bitrate *= frameRate.first / frameRate.second;
1432
+
1433
+           uint8_t qp_i, qp_p, qp_b;
1434
+           qp_i = this->GetIFrameQP();
1435
+           qp_p = this->GetPFrameQP();
1436
+           try { qp_b = this->GetBFrameQP(); } catch (...) { qp_b = 51; }
1437
+           double_t qp = 1 - ((double_t)(min(min(qp_i, qp_p), qp_b)) / 51.0);
1438
+           qp = max(qp * qp, 0.001); // Needs to be at least 0.001.
1439
+
1440
+           looseBitrate = static_cast<uint32_t>(bitrate * qp);
1441
+           break;
1442
+   }
1443
+   strictBitrate = static_cast<uint32_t>(looseBitrate * m_FrameRateReverseDivisor);
1444
+
1445
+   #define PI 3.14159265
1446
+   double_t interpVal = (sin(max(min(strictness, 1.0), 0.0) * 90 * (PI / 180))); // sin curve?
1447
+   uint32_t realBitrate = static_cast<uint32_t>(ceil((strictBitrate * interpVal) + (looseBitrate * (1.0 - interpVal))));
1448
+   this->SetVBVBufferSize(realBitrate);
1449
+}
1450
+
1451
+uint32_t Plugin::AMD::VCEEncoder::GetVBVBufferSize() {
1452
+   uint32_t size;
1453
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_VBV_BUFFER_SIZE, &size);
1454
+   if (res != AMF_OK) {
1455
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1456
+   }
1457
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", size);
1458
+   return size;
1459
+}
1460
+
1461
+void Plugin::AMD::VCEEncoder::SetInitialVBVBufferFullness(double_t fullness) {
1462
+   // Clamp Value
1463
+   fullness = max(min(fullness, 1), 0); // 0 to 100 %
1464
+
1465
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_INITIAL_VBV_BUFFER_FULLNESS, (uint32_t)(fullness * 64));
1466
+   if (res != AMF_OK) {
1467
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %f%% failed with error %ls (code %d).", res, fullness * 100);
1468
+   }
1469
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %f%%.", fullness * 100);
1470
+}
1471
+
1472
+double_t Plugin::AMD::VCEEncoder::GetInitialVBVBufferFullness() {
1473
+   uint32_t vbvBufferFullness;
1474
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_INITIAL_VBV_BUFFER_FULLNESS, &vbvBufferFullness);
1475
+   if (res != AMF_OK) {
1476
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1477
+   }
1478
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %f%%.", vbvBufferFullness / 64.0 * 100.0);
1479
+   return ((double_t)vbvBufferFullness / 64.0);
1480
+}
1481
+
1482
+void Plugin::AMD::VCEEncoder::SetFillerDataEnabled(bool enabled) {
1483
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_FILLER_DATA_ENABLE, enabled);
1484
+   if (res != AMF_OK) {
1485
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1486
+   }
1487
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1488
+}
1489
+
1490
+bool Plugin::AMD::VCEEncoder::IsFillerDataEnabled() {
1491
+   bool enabled;
1492
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_FILLER_DATA_ENABLE, &enabled);
1493
+   if (res != AMF_OK) {
1494
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1495
+   }
1496
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1497
+   return enabled;
1498
+}
1499
+
1500
+void Plugin::AMD::VCEEncoder::SetFrameSkippingEnabled(bool enabled) {
1501
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_RATE_CONTROL_SKIP_FRAME_ENABLE, enabled);
1502
+   if (res != AMF_OK) {
1503
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1504
+   }
1505
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1506
+}
1507
+
1508
+bool Plugin::AMD::VCEEncoder::IsFrameSkippingEnabled() {
1509
+   bool enabled;
1510
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_RATE_CONTROL_SKIP_FRAME_ENABLE, &enabled);
1511
+   if (res != AMF_OK) {
1512
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1513
+   }
1514
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1515
+   return enabled;
1516
+}
1517
+
1518
+void Plugin::AMD::VCEEncoder::SetEnforceHRDRestrictionsEnabled(bool enabled) {
1519
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_ENFORCE_HRD, enabled);
1520
+   if (res != AMF_OK) {
1521
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1522
+   }
1523
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1524
+}
1525
+
1526
+bool Plugin::AMD::VCEEncoder::IsEnforceHRDRestrictionsEnabled() {
1527
+   bool enabled;
1528
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_ENFORCE_HRD, &enabled);
1529
+   if (res != AMF_OK) {
1530
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1531
+   }
1532
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1533
+   return enabled;
1534
+}
1535
+
1536
+void Plugin::AMD::VCEEncoder::SetIDRPeriod(uint32_t period) {
1537
+   // Clamp Value
1538
+   period = max(min(period, 1000), 1); // 1-1000 so that OBS can actually quit.
1539
+
1540
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_IDR_PERIOD, (uint32_t)period);
1541
+   if (res != AMF_OK) {
1542
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, period);
1543
+   }
1544
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", period);
1545
+}
1546
+
1547
+uint32_t Plugin::AMD::VCEEncoder::GetIDRPeriod() {
1548
+   int32_t period;
1549
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_IDR_PERIOD, &period);
1550
+   if (res != AMF_OK) {
1551
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1552
+   }
1553
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", period);
1554
+   return period;
1555
+}
1556
+
1557
+void Plugin::AMD::VCEEncoder::SetBFramePattern(VCEBFramePattern pattern) {
1558
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_B_PIC_PATTERN, (uint32_t)pattern);
1559
+   if (res != AMF_OK) {
1560
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, pattern);
1561
+   }
1562
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", pattern);
1563
+}
1564
+
1565
+Plugin::AMD::VCEBFramePattern Plugin::AMD::VCEEncoder::GetBFramePattern() {
1566
+   uint32_t pattern;
1567
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_B_PIC_PATTERN, &pattern);
1568
+   if (res != AMF_OK) {
1569
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1570
+   }
1571
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", pattern);
1572
+   return (Plugin::AMD::VCEBFramePattern)pattern;
1573
+}
1574
+
1575
+void Plugin::AMD::VCEEncoder::SetBFrameDeltaQP(int8_t qp) {
1576
+   // Clamp Value
1577
+   qp = clamp(qp, -10, 10);
1578
+
1579
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_B_PIC_DELTA_QP, (int32_t)qp);
1580
+   if (res != AMF_OK) {
1581
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, qp);
1582
+   }
1583
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
1584
+}
1585
+
1586
+int8_t Plugin::AMD::VCEEncoder::GetBFrameDeltaQP() {
1587
+   int32_t qp;
1588
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_B_PIC_DELTA_QP, &qp);
1589
+   if (res != AMF_OK) {
1590
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1591
+   }
1592
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", qp);
1593
+   return (int8_t)qp;
1594
+}
1595
+
1596
+void Plugin::AMD::VCEEncoder::SetBFrameReferenceEnabled(bool enabled) {
1597
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_B_REFERENCE_ENABLE, enabled);
1598
+   if (res != AMF_OK) {
1599
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1600
+   }
1601
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1602
+}
1603
+
1604
+bool Plugin::AMD::VCEEncoder::IsBFrameReferenceEnabled() {
1605
+   bool enabled;
1606
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_B_REFERENCE_ENABLE, &enabled);
1607
+   if (res != AMF_OK) {
1608
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1609
+   }
1610
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1611
+   return enabled;
1612
+}
1613
+
1614
+void Plugin::AMD::VCEEncoder::SetBFrameReferenceDeltaQP(int8_t qp) {
1615
+   // Clamp Value
1616
+   qp = clamp(qp, -10, 10);
1617
+
1618
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_REF_B_PIC_DELTA_QP, (int32_t)qp);
1619
+   if (res != AMF_OK) {
1620
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, qp);
1621
+   }
1622
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
1623
+}
1624
+
1625
+int8_t Plugin::AMD::VCEEncoder::GetBFrameReferenceDeltaQP() {
1626
+   int32_t qp;
1627
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_REF_B_PIC_DELTA_QP, &qp);
1628
+   if (res != AMF_OK) {
1629
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1630
+   }
1631
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", qp);
1632
+   return (int8_t)qp;
1633
+}
1634
+
1635
+void Plugin::AMD::VCEEncoder::SetDeblockingFilterEnabled(bool enabled) {
1636
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_DE_BLOCKING_FILTER, enabled);
1637
+   if (res != AMF_OK) {
1638
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1639
+   }
1640
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1641
+}
1642
+
1643
+bool Plugin::AMD::VCEEncoder::IsDeblockingFilterEnabled() {
1644
+   bool enabled;
1645
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_DE_BLOCKING_FILTER, &enabled);
1646
+   if (res != AMF_OK) {
1647
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1648
+   }
1649
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1650
+   return enabled;
1651
+}
1652
+
1653
+void Plugin::AMD::VCEEncoder::SetHalfPixelMotionEstimationEnabled(bool enabled) {
1654
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_MOTION_HALF_PIXEL, enabled);
1655
+   if (res != AMF_OK) {
1656
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1657
+   }
1658
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1659
+}
1660
+
1661
+bool Plugin::AMD::VCEEncoder::IsHalfPixelMotionEstimationEnabled() {
1662
+   bool enabled;
1663
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MOTION_HALF_PIXEL, &enabled);
1664
+   if (res != AMF_OK) {
1665
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1666
+   }
1667
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1668
+   return enabled;
1669
+}
1670
+
1671
+void Plugin::AMD::VCEEncoder::SetQuarterPixelMotionEstimationEnabled(bool enabled) {
1672
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_MOTION_QUARTERPIXEL, enabled);
1673
+   if (res != AMF_OK) {
1674
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1675
+   }
1676
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1677
+}
1678
+
1679
+bool Plugin::AMD::VCEEncoder::IsQuarterPixelMotionEstimationEnabled() {
1680
+   bool enabled;
1681
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MOTION_QUARTERPIXEL, &enabled);
1682
+   if (res != AMF_OK) {
1683
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1684
+   }
1685
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1686
+   return enabled;
1687
+}
1688
+
1689
+//////////////////////////////////////////////////////////////////////////
1690
+// EXPERIMENTAL PROPERTIES - MAY BREAK AT ANY POINT IN TIME!
1691
+//////////////////////////////////////////////////////////////////////////
1692
+// Their effect may vary from driver to driver, card to card.
1693
+
1694
+uint32_t Plugin::AMD::VCEEncoder::GetMaxMBPerSec() {
1695
+   uint32_t maxMBPerSec;
1696
+   AMF_RESULT res = m_AMFEncoder->GetProperty(L"MaxMBPerSec", &maxMBPerSec);
1697
+   if (res != AMF_OK) {
1698
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1699
+   }
1700
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", maxMBPerSec);
1701
+   return maxMBPerSec;
1702
+}
1703
+
1704
+void Plugin::AMD::VCEEncoder::SetHeaderInsertionSpacing(uint32_t spacing) {
1705
+   // Clamp Value
1706
+   spacing = max(min(spacing, m_FrameRate.second * 1000), 0);
1707
+
1708
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_HEADER_INSERTION_SPACING, (uint32_t)spacing);
1709
+   if (res != AMF_OK) {
1710
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, spacing);
1711
+   }
1712
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", spacing);
1713
+}
1714
+
1715
+uint32_t Plugin::AMD::VCEEncoder::GetHeaderInsertionSpacing() {
1716
+   int32_t headerInsertionSpacing;
1717
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_HEADER_INSERTION_SPACING, &headerInsertionSpacing);
1718
+   if (res != AMF_OK) {
1719
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1720
+   }
1721
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", headerInsertionSpacing);
1722
+   return headerInsertionSpacing;
1723
+}
1724
+
1725
+void Plugin::AMD::VCEEncoder::SetMaximumLongTermReferenceFrames(uint32_t maximumLTRFrames) {
1726
+   // Clamp Parameter Value
1727
+   maximumLTRFrames = max(min(maximumLTRFrames, 2), 0);
1728
+
1729
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_MAX_LTR_FRAMES, (uint32_t)maximumLTRFrames);
1730
+   if (res != AMF_OK) {
1731
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, maximumLTRFrames);
1732
+   }
1733
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", maximumLTRFrames);
1734
+}
1735
+
1736
+uint32_t Plugin::AMD::VCEEncoder::GetMaximumLongTermReferenceFrames() {
1737
+   uint32_t maximumLTRFrames;
1738
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MAX_LTR_FRAMES, &maximumLTRFrames);
1739
+   if (res != AMF_OK) {
1740
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1741
+   }
1742
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", maximumLTRFrames);
1743
+   return maximumLTRFrames;
1744
+}
1745
+
1746
+void Plugin::AMD::VCEEncoder::SetCodingType(VCECodingType type) {
1747
+   AMF_RESULT res = m_AMFEncoder->SetProperty(L"CABACEnable", type);
1748
+   if (res != AMF_OK) {
1749
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, Utility::CodingTypeAsString(type));
1750
+   }
1751
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", Utility::CodingTypeAsString(type));
1752
+}
1753
+
1754
+VCECodingType Plugin::AMD::VCEEncoder::GetCodingType() {
1755
+   uint64_t type;
1756
+   AMF_RESULT res = m_AMFEncoder->GetProperty(L"CABACEnable", &type);
1757
+   if (res != AMF_OK) {
1758
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1759
+   }
1760
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", Utility::CodingTypeAsString((VCECodingType)type));
1761
+   return (VCECodingType)type;
1762
+}
1763
+
1764
+void Plugin::AMD::VCEEncoder::SetMaximumAccessUnitSize(uint32_t size) {
1765
+   // Clamp Value
1766
+   size = max(min(size, 100000000), 0); // 1kbit to 100mbit.
1767
+
1768
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_MAX_AU_SIZE, (uint32_t)size);
1769
+   if (res != AMF_OK) {
1770
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d bits failed with error %ls (code %d).", res, size);
1771
+   }
1772
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d bits.", size);
1773
+}
1774
+
1775
+uint32_t Plugin::AMD::VCEEncoder::GetMaximumAccessUnitSize() {
1776
+   uint32_t size;
1777
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MAX_AU_SIZE, &size);
1778
+   if (res != AMF_OK) {
1779
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1780
+   }
1781
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", size);
1782
+   return size;
1783
+}
1784
+
1785
+void Plugin::AMD::VCEEncoder::SetWaitForTaskEnabled(bool enabled) {
1786
+   AMF_RESULT res = m_AMFEncoder->SetProperty(L"WaitForTask", enabled);
1787
+   if (res != AMF_OK) {
1788
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1789
+   }
1790
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1791
+}
1792
+
1793
+bool Plugin::AMD::VCEEncoder::IsWaitForTaskEnabled() {
1794
+   bool enabled;
1795
+   AMF_RESULT res = m_AMFEncoder->GetProperty(L"WaitForTask", &enabled);
1796
+   if (res != AMF_OK) {
1797
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1798
+   }
1799
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1800
+   return enabled;
1801
+}
1802
+
1803
+void Plugin::AMD::VCEEncoder::SetPreAnalysisPassEnabled(bool enabled) {
1804
+   AMF_RESULT res = m_AMFEncoder->SetProperty(L"RateControlPreanalysisEnable", enabled);
1805
+   if (res != AMF_OK) {
1806
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1807
+   }
1808
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1809
+}
1810
+
1811
+bool Plugin::AMD::VCEEncoder::IsPreAnalysisPassEnabled() {
1812
+   bool enabled;
1813
+   AMF_RESULT res = m_AMFEncoder->GetProperty(L"RateControlPreanalysisEnable", &enabled);
1814
+   if (res != AMF_OK) {
1815
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1816
+   }
1817
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1818
+   return enabled;
1819
+}
1820
+
1821
+void Plugin::AMD::VCEEncoder::SetVBAQEnabled(bool enabled) {
1822
+   const wchar_t* names[] = {
1823
+       L"EnableVBAQ", // 16.12.1
1824
+       L"EanbleVBAQ", // 16.11.5 and below.
1825
+   };
1826
+
1827
+   bool enabledTest;
1828
+   AMF_RESULT res = AMF_INVALID_ARG;
1829
+   for (size_t i = 0; i < _countof(names); i++) {
1830
+       if (m_AMFEncoder->GetProperty(names[i], &enabledTest) == AMF_OK) {
1831
+           m_AMFConverter->SetProperty(names[i], enabled);
1832
+           res = m_AMFEncoder->SetProperty(names[i], enabled);
1833
+           break;
1834
+       }
1835
+   }
1836
+   if (res != AMF_OK) {
1837
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1838
+   }
1839
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1840
+}
1841
+
1842
+bool Plugin::AMD::VCEEncoder::IsVBAQEnabled() {
1843
+   const wchar_t* names[] = {
1844
+       L"EnableVBAQ", // 16.12.1
1845
+       L"EanbleVBAQ", // 16.11.5 and below.
1846
+   };
1847
+
1848
+   bool enabled;
1849
+   AMF_RESULT res = AMF_INVALID_ARG;
1850
+   for (size_t i = 0; i < _countof(names); i++) {
1851
+       res = m_AMFEncoder->GetProperty(names[i], &enabled);
1852
+       if (res == AMF_OK) {
1853
+           break;
1854
+       }
1855
+   }
1856
+   if (res != AMF_OK) {
1857
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1858
+   }
1859
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1860
+   return enabled;
1861
+}
1862
+
1863
+void Plugin::AMD::VCEEncoder::SetGOPSize(uint32_t size) {
1864
+   AMF_RESULT res = m_AMFEncoder->SetProperty(L"GOPSize", (uint32_t)size);
1865
+   if (res != AMF_OK) {
1866
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, size);
1867
+   }
1868
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", size);
1869
+}
1870
+
1871
+uint32_t Plugin::AMD::VCEEncoder::GetGOPSize() {
1872
+   uint32_t size;
1873
+   AMF_RESULT res = m_AMFEncoder->GetProperty(L"GOPSize", &size);
1874
+   if (res != AMF_OK) {
1875
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1876
+   }
1877
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", size);
1878
+   return size;
1879
+}
1880
+
1881
+void Plugin::AMD::VCEEncoder::SetGOPAlignmentEnabled(bool enabled) {
1882
+   AMF_RESULT res = m_AMFEncoder->SetProperty(L"EnableGOPAlignment", enabled);
1883
+   if (res != AMF_OK) {
1884
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1885
+   }
1886
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1887
+}
1888
+
1889
+bool Plugin::AMD::VCEEncoder::IsGOPAlignementEnabled() {
1890
+   bool enabled;
1891
+   AMF_RESULT res = m_AMFEncoder->GetProperty(L"EnableGOPAlignment", &enabled);
1892
+   if (res != AMF_OK) {
1893
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1894
+   }
1895
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", enabled ? "Enabled" : "Disabled");
1896
+   return enabled;
1897
+}
1898
+
1899
+void Plugin::AMD::VCEEncoder::SetMaximumReferenceFrames(uint32_t numFrames) {
1900
+   auto caps = VCECapabilities::GetInstance()->GetAdapterCapabilities(m_API, m_APIAdapter, VCEEncoderType_AVC);
1901
+   numFrames = clamp(numFrames,
1902
+       caps.minReferenceFrames,
1903
+       caps.maxReferenceFrames);
1904
+
1905
+   AMF_RESULT res = m_AMFEncoder->SetProperty(L"MaxNumRefFrames", (uint32_t)numFrames);
1906
+   if (res != AMF_OK) {
1907
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, numFrames);
1908
+   }
1909
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", numFrames);
1910
+}
1911
+
1912
+uint32_t Plugin::AMD::VCEEncoder::GetMaximumReferenceFrames() {
1913
+   uint32_t numFrames;
1914
+   AMF_RESULT res = m_AMFEncoder->GetProperty(L"MaxNumRefFrames", &numFrames);
1915
+   if (res != AMF_OK) {
1916
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1917
+   }
1918
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", numFrames);
1919
+   return numFrames;
1920
+}
1921
+
1922
+void Plugin::AMD::VCEEncoder::SetAspectRatio(uint32_t num, uint32_t den) {
1923
+   AMF_RESULT res = m_AMFEncoder->SetProperty(L"AspectRatio", ::AMFConstructRate(num, den));
1924
+   if (res != AMF_OK) {
1925
+       std::vector<char> msgBuf;
1926
+       sprintf(msgBuf.data(), "%d:%d", num, den);
1927
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, msgBuf.data());
1928
+   }
1929
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d:%d.", num, den);
1930
+}
1931
+
1932
+std::pair<uint32_t, uint32_t> Plugin::AMD::VCEEncoder::GetAspectRatio() {
1933
+   AMFRate aspectRatio;
1934
+   AMF_RESULT res = m_AMFEncoder->GetProperty(L"AspectRatio", &aspectRatio);
1935
+   if (res != AMF_OK) {
1936
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1937
+   }
1938
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d:%d.", aspectRatio.num, aspectRatio.den);
1939
+   return std::pair<uint32_t, uint32_t>(aspectRatio.num, aspectRatio.den);
1940
+}
1941
+
1942
+void Plugin::AMD::VCEEncoder::SetIntraRefreshMacroblocksPerSlot(uint32_t mbs) {
1943
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_INTRA_REFRESH_NUM_MBS_PER_SLOT, (uint32_t)mbs);
1944
+   if (res != AMF_OK) {
1945
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, mbs);
1946
+   }
1947
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", mbs);
1948
+}
1949
+
1950
+uint32_t Plugin::AMD::VCEEncoder::GetIntraRefreshMacroblocksPerSlot() {
1951
+   int32_t mbs;
1952
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_INTRA_REFRESH_NUM_MBS_PER_SLOT, &mbs);
1953
+   if (res != AMF_OK) {
1954
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1955
+   }
1956
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", mbs);
1957
+   return mbs;
1958
+}
1959
+
1960
+void Plugin::AMD::VCEEncoder::SetIntraRefreshNumberOfStripes(uint32_t stripes) {
1961
+   stripes = clamp(stripes, 0, INT_MAX);
1962
+
1963
+   AMF_RESULT res = m_AMFEncoder->SetProperty(L"IntraRefreshNumOfStripes", (uint32_t)stripes);
1964
+   if (res != AMF_OK) {
1965
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, stripes);
1966
+   }
1967
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", stripes);
1968
+
1969
+}
1970
+
1971
+uint32_t Plugin::AMD::VCEEncoder::GetIntraRefreshNumberOfStripes() {
1972
+   uint32_t stripes;
1973
+   AMF_RESULT res = m_AMFEncoder->GetProperty(L"IntraRefreshNumOfStripes", &stripes);
1974
+   if (res != AMF_OK) {
1975
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1976
+   }
1977
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", stripes);
1978
+   return stripes;
1979
+}
1980
+
1981
+void Plugin::AMD::VCEEncoder::SetSlicesPerFrame(uint32_t slices) {
1982
+   slices = max(slices, 1);
1983
+
1984
+   AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_SLICES_PER_FRAME, (uint32_t)slices);
1985
+   if (res != AMF_OK) {
1986
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, slices);
1987
+   }
1988
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", slices);
1989
+}
1990
+
1991
+uint32_t Plugin::AMD::VCEEncoder::GetSlicesPerFrame() {
1992
+   uint32_t slices;
1993
+   AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_SLICES_PER_FRAME, &slices);
1994
+   if (res != AMF_OK) {
1995
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1996
+   }
1997
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", slices);
1998
+   return slices;
1999
+}
2000
+
2001
+void Plugin::AMD::VCEEncoder::SetSliceMode(VCESliceMode mode) {
2002
+   AMF_RESULT res = m_AMFEncoder->SetProperty(L"SliceMode", (uint32_t)mode);
2003
+   if (res != AMF_OK) {
2004
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, Utility::SliceModeAsString(mode));
2005
+   }
2006
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", Utility::SliceModeAsString(mode));
2007
+}
2008
+
2009
+Plugin::AMD::VCESliceMode Plugin::AMD::VCEEncoder::GetSliceMode() {
2010
+   uint32_t mode;
2011
+   AMF_RESULT res = m_AMFEncoder->GetProperty(L"SliceMode", &mode);
2012
+   if (res != AMF_OK) {
2013
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
2014
+   }
2015
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", Utility::SliceModeAsString((VCESliceMode)mode));
2016
+   return (VCESliceMode)mode;
2017
+}
2018
+
2019
+void Plugin::AMD::VCEEncoder::SetMaximumSliceSize(uint32_t size) {
2020
+   size = clamp(size, 1, INT_MAX);
2021
+
2022
+   AMF_RESULT res = m_AMFEncoder->SetProperty(L"MaxSliceSize", (uint32_t)size);
2023
+   if (res != AMF_OK) {
2024
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, size);
2025
+   }
2026
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", size);
2027
+}
2028
+
2029
+uint32_t Plugin::AMD::VCEEncoder::GetMaximumSliceSize() {
2030
+   uint32_t size;
2031
+   AMF_RESULT res = m_AMFEncoder->GetProperty(L"MaxSliceSize", &size);
2032
+   if (res != AMF_OK) {
2033
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
2034
+   }
2035
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", size);
2036
+   return size;
2037
+}
2038
+
2039
+void Plugin::AMD::VCEEncoder::SetSliceControlMode(VCESliceControlMode mode) {
2040
+   AMF_RESULT res = m_AMFEncoder->SetProperty(L"SliceControlMode", (uint32_t)mode);
2041
+   if (res != AMF_OK) {
2042
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, Utility::SliceControlModeAsString(mode));
2043
+   }
2044
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", Utility::SliceControlModeAsString(mode));
2045
+}
2046
+
2047
+Plugin::AMD::VCESliceControlMode Plugin::AMD::VCEEncoder::GetSliceControlMode() {
2048
+   uint32_t mode;
2049
+   AMF_RESULT res = m_AMFEncoder->GetProperty(L"SliceControlMode", &mode);
2050
+   if (res != AMF_OK) {
2051
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
2052
+   }
2053
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", Utility::SliceControlModeAsString((VCESliceControlMode)mode));
2054
+   return (VCESliceControlMode)mode;
2055
+}
2056
+
2057
+void Plugin::AMD::VCEEncoder::SetSliceControlSize(uint32_t size) {
2058
+   // If GetSliceMode() is VCESliceMode_Vertical, then it outputs nothing with the following settings:
2059
+   // - SliceControlMode: VCESliceControlMode_Macroblock
2060
+   // - SliceControlSize: < 3600
2061
+   // If GetSliceMode() is VCESliceMode_Horizontal, then it outputs nothing with the following settings:
2062
+   // - SliceControlMode: VCESliceControlMode_Macroblock
2063
+   // - SliceControlSize: < 32
2064
+
2065
+   // H264 Macroblock = 16*16 = 256
2066
+   switch (GetSliceControlMode()) {
2067
+       case VCESliceControlMode_Off:
2068
+           return;
2069
+       case VCESliceControlMode_Macroblock:
2070
+           size = clamp(size, 0, (uint32_t)(ceil(m_FrameSize.first / 16) * ceil(m_FrameSize.second / 16)));
2071
+           break;
2072
+       case VCESliceControlMode_Macroblock_Row:
2073
+           size = clamp(size, 0, (uint32_t)ceil(m_FrameSize.second / 16));
2074
+           break;
2075
+   }
2076
+
2077
+   AMF_RESULT res = m_AMFEncoder->SetProperty(L"SliceControlSize", (uint32_t)size);
2078
+   if (res != AMF_OK) {
2079
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, size);
2080
+   }
2081
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", size);
2082
+}
2083
+
2084
+uint32_t Plugin::AMD::VCEEncoder::GetSliceControlSize() {
2085
+   uint32_t size;
2086
+   AMF_RESULT res = m_AMFEncoder->GetProperty(L"SliceControlSize", &size);
2087
+   if (res != AMF_OK) {
2088
+       ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
2089
+   }
2090
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", size);
2091
+   return size;
2092
+}
2093
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/amf.cpp Added
270
 
1
@@ -0,0 +1,268 @@
2
+/*
3
+MIT License
4
+
5
+Copyright (c) 2016 Michael Fabian Dirks
6
+
7
+Permission is hereby granted, free of charge, to any person obtaining a copy
8
+of this software and associated documentation files (the "Software"), to deal
9
+in the Software without restriction, including without limitation the rights
10
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+copies of the Software, and to permit persons to whom the Software is
12
+furnished to do so, subject to the following conditions:
13
+
14
+The above copyright notice and this permission notice shall be included in all
15
+copies or substantial portions of the Software.
16
+
17
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+SOFTWARE.
24
+*/
25
+
26
+//////////////////////////////////////////////////////////////////////////
27
+// Includes
28
+//////////////////////////////////////////////////////////////////////////
29
+#include <vector>
30
+#include <mutex>
31
+
32
+#include "amf.h"
33
+#include "windows.h"
34
+
35
+// AMD AMF SDK
36
+#include "components\Component.h"
37
+#include "components\ComponentCaps.h"
38
+#include "components\VideoEncoderVCE.h"
39
+
40
+//////////////////////////////////////////////////////////////////////////
41
+// Code
42
+//////////////////////////////////////////////////////////////////////////
43
+using namespace Plugin::AMD;
44
+
45
+class CustomWriter : public amf::AMFTraceWriter {
46
+   public:
47
+   virtual void Write(const wchar_t* scope, const wchar_t* message) override {
48
+       const wchar_t* realmsg = &(message[(33 + wcslen(scope) + 2)]); // Skip Time & Scope
49
+       size_t msgLen = wcslen(realmsg) - (sizeof(wchar_t));
50
+
51
+       blog(LOG_INFO, "[AMF Encoder] [%.*ls][%ls] %.*ls", 
52
+           12, &(message[11]),
53
+           scope, 
54
+           msgLen, realmsg);
55
+   }
56
+
57
+   virtual void Flush() override {}
58
+
59
+   static std::shared_ptr<CustomWriter> GetInstance() {
60
+       static std::shared_ptr<CustomWriter> __instance = std::make_shared<CustomWriter>();
61
+       static std::mutex __mutex;
62
+
63
+       const std::lock_guard<std::mutex> lock(__mutex);
64
+       return __instance;
65
+   }
66
+};
67
+
68
+std::shared_ptr<Plugin::AMD::AMF> Plugin::AMD::AMF::GetInstance() {
69
+   static std::shared_ptr<AMF> __instance = std::make_shared<AMF>();
70
+   static std::mutex __mutex;
71
+
72
+   const std::lock_guard<std::mutex> lock(__mutex);
73
+   return __instance;
74
+}
75
+
76
+Plugin::AMD::AMF::AMF() {
77
+   AMF_RESULT res = AMF_OK;
78
+
79
+   // Initialize AMF Library
80
+   AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> Initializing...");
81
+
82
+   #pragma region Null Class Members
83
+   m_TimerPeriod = 0;
84
+   m_AMFVersion_Compiler = 0;
85
+   m_AMFVersion_Runtime = 0;
86
+   m_AMFModule = 0;
87
+
88
+   m_AMFFactory = nullptr;
89
+   m_AMFTrace = nullptr;
90
+   m_AMFDebug = nullptr;
91
+   AMFQueryVersion = nullptr;
92
+   AMFInit = nullptr;
93
+   #pragma endregion Null Class Members
94
+
95
+   /// Load AMF Runtime into Memory.
96
+   m_AMFModule = LoadLibraryW(AMF_DLL_NAME);
97
+   if (!m_AMFModule) {
98
+       DWORD error = GetLastError();
99
+       std::vector<char> buf(1024);
100
+       sprintf(buf.data(), "Unable to load '%ls', error code %ld.", AMF_DLL_NAME, error);
101
+       AMF_LOG_ERROR("%s", buf.data());
102
+       throw std::exception(buf.data(), error);
103
+   }
104
+   AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> Loaded '%ls'.", AMF_DLL_NAME);
105
+   #ifdef _WIN32 // Windows: Get Product Version
106
+   std::vector<char> verbuf(GetFileVersionInfoSizeW(AMF_DLL_NAME, nullptr));
107
+   GetFileVersionInfoW(AMF_DLL_NAME, 0, (DWORD)verbuf.size(), verbuf.data());
108
+
109
+   void* pBlock = verbuf.data();
110
+
111
+   // Read the list of languages and code pages.
112
+   struct LANGANDCODEPAGE {
113
+       WORD wLanguage;
114
+       WORD wCodePage;
115
+   } *lpTranslate;
116
+   UINT cbTranslate = sizeof(LANGANDCODEPAGE);
117
+
118
+   VerQueryValueA(pBlock, "\\VarFileInfo\\Translation", (LPVOID*)&lpTranslate, &cbTranslate);
119
+
120
+   std::vector<char> buf(1024);
121
+   sprintf(buf.data(), "%s%04x%04x%s",
122
+       "\\StringFileInfo\\",
123
+       lpTranslate[0].wLanguage,
124
+       lpTranslate[0].wCodePage,
125
+       "\\ProductVersion");
126
+
127
+   // Retrieve file description for language and code page "i". 
128
+   void* pProductVersion;
129
+   uint32_t lProductVersionSize;
130
+   VerQueryValueA(pBlock, buf.data(), &pProductVersion, &lProductVersionSize);
131
+   #endif _WIN32 // Windows: Get Product Version
132
+
133
+   /// Find Function for Querying AMF Version.
134
+   #pragma region Query AMF Runtime Version
135
+   AMFQueryVersion = (AMFQueryVersion_Fn)GetProcAddress(m_AMFModule, AMF_QUERY_VERSION_FUNCTION_NAME);
136
+   if (!AMFQueryVersion) {
137
+       DWORD error = GetLastError();
138
+       std::vector<char> buf(1024);
139
+       sprintf(buf.data(), "<Plugin::AMD::AMF::AMF> Finding Address of Function '%s' failed with error code %ld.", AMF_QUERY_VERSION_FUNCTION_NAME, error);
140
+       AMF_LOG_ERROR("%s", buf.data());
141
+       throw std::exception(buf.data(), error);
142
+   }
143
+   /// Query Runtime Version
144
+   m_AMFVersion_Compiler = AMF_FULL_VERSION;
145
+   res = AMFQueryVersion(&m_AMFVersion_Runtime);
146
+   if (res != AMF_OK)
147
+       ThrowExceptionWithAMFError("<Plugin::AMD::AMF::AMF> Querying Version failed with error %ls (code %ld).", res);
148
+   #pragma endregion Query AMF Runtime Version
149
+
150
+       /// Find Function for Initializing AMF.
151
+   AMFInit = (AMFInit_Fn)GetProcAddress(m_AMFModule, AMF_INIT_FUNCTION_NAME);
152
+   if (!AMFInit) {
153
+       DWORD error = GetLastError();
154
+       std::vector<char> buf(1024);
155
+       sprintf(buf.data(), "<Plugin::AMD::AMF::AMF> Finding Address of Function '%s' failed with error code %ld.", AMF_INIT_FUNCTION_NAME, error);
156
+       AMF_LOG_ERROR("%s", buf.data());
157
+       throw std::exception(buf.data(), error);
158
+   } else {
159
+       res = AMFInit(m_AMFVersion_Runtime, &m_AMFFactory);
160
+       if (res != AMF_OK)
161
+           ThrowExceptionWithAMFError("<Plugin::AMD::AMF::AMF> Initializing AMF Library failed with error %ls (code %ld).", res);
162
+   }
163
+   AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> AMF Library initialized.");
164
+
165
+   /// Retrieve Trace Object.
166
+   res = m_AMFFactory->GetTrace(&m_AMFTrace);
167
+   if (res != AMF_OK) {
168
+       ThrowExceptionWithAMFError("<Plugin::AMD::AMF::AMF> Retrieving Trace object failed with error %ls (code %ld).", res);
169
+   }
170
+
171
+   /// Retrieve Debug Object.
172
+   res = m_AMFFactory->GetDebug(&m_AMFDebug);
173
+   if (res != AMF_OK) {
174
+       AMF_LOG_ERROR("<Plugin::AMD::AMF::AMF> Retrieving Debug object failed with error code %ls (code %ld).", res);
175
+       throw std::exception("", res);
176
+   }
177
+
178
+   /// Register Custom Trace Writer and disable Debug Tracing.
179
+   m_AMFTrace->RegisterWriter(L"OBSWriter", CustomWriter::GetInstance().get(), true);
180
+   this->EnableDebugTrace(false);
181
+
182
+   // Log success
183
+   AMF_LOG_INFO("Version " PLUGIN_VERSION_TEXT " loaded (Compiled: %d.%d.%d.%d, Runtime: %d.%d.%d.%d, Library: %.*s).",
184
+       (uint16_t)((m_AMFVersion_Compiler >> 48ull) & 0xFFFF),
185
+       (uint16_t)((m_AMFVersion_Compiler >> 32ull) & 0xFFFF),
186
+       (uint16_t)((m_AMFVersion_Compiler >> 16ull) & 0xFFFF),
187
+       (uint16_t)((m_AMFVersion_Compiler & 0xFFFF)),
188
+       (uint16_t)((m_AMFVersion_Runtime >> 48ull) & 0xFFFF),
189
+       (uint16_t)((m_AMFVersion_Runtime >> 32ull) & 0xFFFF),
190
+       (uint16_t)((m_AMFVersion_Runtime >> 16ull) & 0xFFFF),
191
+       (uint16_t)((m_AMFVersion_Runtime & 0xFFFF)),
192
+       lProductVersionSize, pProductVersion
193
+   );
194
+
195
+   AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> Initialized.");
196
+}
197
+
198
+Plugin::AMD::AMF::~AMF() {
199
+   AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> Finalizing.");
200
+
201
+   /// Unregister Writer
202
+   if (m_AMFTrace)
203
+       m_AMFTrace->UnregisterWriter(L"OBSWriter");
204
+
205
+   // Free Library again
206
+   if (m_AMFModule)
207
+       FreeLibrary(m_AMFModule);
208
+
209
+   #pragma region Null Class Members
210
+   m_TimerPeriod = 0;
211
+   m_AMFVersion_Compiler = 0;
212
+   m_AMFVersion_Runtime = 0;
213
+   m_AMFModule = 0;
214
+
215
+   m_AMFFactory = nullptr;
216
+   m_AMFTrace = nullptr;
217
+   m_AMFDebug = nullptr;
218
+   AMFQueryVersion = nullptr;
219
+   AMFInit = nullptr;
220
+   #pragma endregion Null Class Members
221
+
222
+   AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> Finalized.");
223
+}
224
+
225
+amf::AMFFactory* Plugin::AMD::AMF::GetFactory() {
226
+   return m_AMFFactory;
227
+}
228
+
229
+amf::AMFTrace* Plugin::AMD::AMF::GetTrace() {
230
+   return m_AMFTrace;
231
+}
232
+
233
+amf::AMFDebug* Plugin::AMD::AMF::GetDebug() {
234
+   return m_AMFDebug;
235
+}
236
+
237
+void Plugin::AMD::AMF::EnableDebugTrace(bool enable) {
238
+   if (!m_AMFTrace)
239
+       throw std::exception(__FUNCTION_NAME__ " called without a AMFTrace object!");
240
+   if (!m_AMFDebug)
241
+       throw std::exception(__FUNCTION_NAME__ " called without a AMFDebug object!");
242
+
243
+   m_AMFTrace->EnableWriter(AMF_TRACE_WRITER_CONSOLE, false);
244
+   m_AMFTrace->SetWriterLevel(AMF_TRACE_WRITER_CONSOLE, AMF_TRACE_ERROR);
245
+   #ifdef _DEBUG
246
+   m_AMFTrace->EnableWriter(AMF_TRACE_WRITER_DEBUG_OUTPUT, true);
247
+   m_AMFTrace->SetWriterLevel(AMF_TRACE_WRITER_DEBUG_OUTPUT, AMF_TRACE_TEST);
248
+   m_AMFTrace->SetPath(L"C:/AMFTrace.log");
249
+   #else
250
+   m_AMFTrace->EnableWriter(AMF_TRACE_WRITER_DEBUG_OUTPUT, false);
251
+   m_AMFTrace->SetWriterLevel(AMF_TRACE_WRITER_DEBUG_OUTPUT, AMF_TRACE_ERROR);
252
+   #endif
253
+   m_AMFTrace->EnableWriter(AMF_TRACE_WRITER_FILE, false);
254
+   m_AMFTrace->SetWriterLevel(AMF_TRACE_WRITER_FILE, AMF_TRACE_ERROR);
255
+
256
+   if (enable) {
257
+       m_AMFDebug->AssertsEnable(true);
258
+       m_AMFDebug->EnablePerformanceMonitor(true);
259
+       m_AMFTrace->TraceEnableAsync(true);
260
+       m_AMFTrace->SetGlobalLevel(AMF_TRACE_TEST);
261
+       m_AMFTrace->SetWriterLevel(L"OBSWriter", AMF_TRACE_TEST);
262
+   } else {
263
+       m_AMFDebug->AssertsEnable(false);
264
+       m_AMFDebug->EnablePerformanceMonitor(false);
265
+       m_AMFTrace->TraceEnableAsync(true);
266
+       m_AMFTrace->SetGlobalLevel(AMF_TRACE_WARNING);
267
+       m_AMFTrace->SetWriterLevel(L"OBSWriter", AMF_TRACE_WARNING);
268
+   }
269
+}
270
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Source/api-base.cpp -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/api-base.cpp Changed
196
 
1
@@ -30,6 +30,8 @@
2
 
3
 #include "api-d3d9.h"
4
 #include "api-d3d11.h"
5
+#include "api-host.h"
6
+#include "api-opengl.h"
7
 
8
 #if defined(_WIN32) || defined(_WIN64)
9
 #include <windows.h>
10
@@ -39,116 +41,110 @@
11
 //////////////////////////////////////////////////////////////////////////
12
 // Code
13
 //////////////////////////////////////////////////////////////////////////
14
+using namespace Plugin::API;
15
 
16
-Plugin::API::Device::Device() {
17
-   this->Name = "Default";
18
-   this->UniqueId = "";
19
+bool Plugin::API::operator<(const Plugin::API::Adapter & left, const Plugin::API::Adapter & right) {
20
+   if (left == right)
21
+       return left.Name < right.Name;
22
+   else
23
+       return (((uint64_t)left.idLow + ((uint64_t)left.idHigh << 32)) < ((uint64_t)right.idLow + ((uint64_t)right.idHigh << 32)));
24
 }
25
 
26
-Plugin::API::Device::Device(std::string Name, std::string UniqueId) {
27
-   this->Name = Name;
28
-   this->UniqueId = UniqueId;
29
-}
30
-
31
-Plugin::API::Device::~Device() {
32
-}
33
-
34
-bool Plugin::API::operator<(const Plugin::API::Device & left, const Plugin::API::Device& right) {
35
-   return left.UniqueId < right.UniqueId;
36
-}
37
-
38
-bool Plugin::API::operator>(const Plugin::API::Device & left, const Plugin::API::Device& right) {
39
+bool Plugin::API::operator>(const Plugin::API::Adapter & left, const Plugin::API::Adapter & right) {
40
    return right < left;
41
 }
42
 
43
-bool Plugin::API::operator<=(const Plugin::API::Device & left, const Plugin::API::Device& right) {
44
+bool Plugin::API::operator<=(const Plugin::API::Adapter & left, const Plugin::API::Adapter & right) {
45
    return !(right < left);
46
 }
47
 
48
-bool Plugin::API::operator>=(const Plugin::API::Device & left, const Plugin::API::Device& right) {
49
+bool Plugin::API::operator>=(const Plugin::API::Adapter & left, const Plugin::API::Adapter & right) {
50
    return !(left < right);
51
 }
52
 
53
-bool Plugin::API::operator==(const Plugin::API::Device & left, const Plugin::API::Device& right) {
54
-   return left.UniqueId == right.UniqueId;
55
+bool Plugin::API::operator==(const Plugin::API::Adapter & left, const Plugin::API::Adapter & right) {
56
+   return ((left.idLow == right.idLow) && (right.idHigh == right.idHigh));
57
 }
58
 
59
-bool Plugin::API::operator!=(const Plugin::API::Device & left, const Plugin::API::Device& right) {
60
+bool Plugin::API::operator!=(const Plugin::API::Adapter & left, const Plugin::API::Adapter & right) {
61
    return !(left == right);
62
 }
63
 
64
-std::vector<Plugin::API::Device> Plugin::API::APIBase::EnumerateDevices() {
65
-   // Build a list of Devices
66
-   #if defined(_WIN32) || defined(_WIN64)
67
+//////////////////////////////////////////////////////////////////////////
68
+// API Index
69
+//////////////////////////////////////////////////////////////////////////
70
+static std::vector<std::shared_ptr<Base>> s_APIInstances;
71
+
72
+void Plugin::API::Base::Initialize() {
73
+   // DirectX 11
74
+   #ifdef _WIN32
75
    if (IsWindows8OrGreater()) {
76
-       return Plugin::API::Direct3D11::EnumerateDevices();
77
-   } else if (IsWindowsXPOrGreater()) {
78
-       //return Plugin::API::Direct3D9::EnumerateDevices();
79
-   } else
80
-       #endif 
81
-   { // OpenGL
82
-       //return Plugin::API::OpenGL::EnumerateDevices();
83
+       s_APIInstances.insert(s_APIInstances.end(), std::make_shared<Direct3D11>());
84
    }
85
-   return std::vector<Plugin::API::Device>();
86
-}
87
+   #endif
88
 
89
-Plugin::API::Device Plugin::API::APIBase::GetDeviceForUniqueId(std::string uniqueId) {
90
-   auto devices = EnumerateDevices();
91
-   for (auto device : devices) {
92
-       if (device.UniqueId == uniqueId)
93
-           return device;
94
+   // DirectX 9
95
+   #ifdef _WIN32
96
+   if (IsWindowsXPOrGreater()) {
97
+       s_APIInstances.insert(s_APIInstances.end(), std::make_shared<Direct3D9>());
98
    }
99
-   return Plugin::API::Device();
100
-}
101
+   #endif
102
 
103
-std::unique_ptr<Plugin::API::APIBase> Plugin::API::APIBase::CreateBestAvailableAPI(Plugin::API::Device device) {
104
-   std::unique_ptr<Plugin::API::APIBase> retVal = std::make_unique<Plugin::API::APIBase>();
105
-   #if defined(_WIN32) || defined(_WIN64)
106
-   if (IsWindows8OrGreater()) {
107
-       retVal = std::make_unique<Plugin::API::Direct3D11>(device);
108
-   } else if (IsWindowsXPOrGreater()) {
109
-       //retVal = std::make_unique<Plugin::API::Direct3D9>(device);
110
-   } else
111
-       #endif 
112
-   { // OpenGL
113
-     //return Plugin::API::OpenGL::OpenGL(device);
114
+   // OpenGL
115
+   {
116
+       s_APIInstances.insert(s_APIInstances.end(), std::make_shared<OpenGL>());
117
    }
118
-   return retVal;
119
-}
120
 
121
-Plugin::API::APIType Plugin::API::APIBase::GetBestAvailableAPI() {
122
-   #if defined(_WIN32) || defined(_WIN64)
123
-   if (IsWindows8OrGreater()) {
124
-       return APIType_Direct3D11;
125
-   } else if (IsWindowsXPOrGreater()) {
126
-       return APIType_Direct3D9;
127
-   } else
128
-       #endif 
129
-   { // OpenGL
130
-       return APIType_OpenGL;
131
+   // Host
132
+   {
133
+       s_APIInstances.insert(s_APIInstances.end(), std::make_shared<Host>());
134
    }
135
-   return APIType_Base;
136
 }
137
 
138
-Plugin::API::APIBase::APIBase() {
139
-   myDevice = Plugin::API::Device();
140
+size_t Plugin::API::Base::GetAPICount() {
141
+   return s_APIInstances.size();
142
 }
143
 
144
-Plugin::API::APIBase::APIBase(Device device) {
145
-   myDevice = device;
146
+std::shared_ptr<Base> Plugin::API::Base::GetAPIInstance(size_t index) {
147
+   auto indAPI = s_APIInstances.begin();
148
+   for (size_t n = 0; n < index; n++)
149
+       indAPI++;
150
+
151
+   if (indAPI == s_APIInstances.end())
152
+       throw std::exception("Invalid API Index");
153
+
154
+   return *indAPI;
155
 }
156
 
157
-Plugin::API::APIBase::~APIBase() {
158
+std::string Plugin::API::Base::GetAPIName(size_t index) {
159
+   auto indAPI = s_APIInstances.begin();
160
+   indAPI + index; // Advanced by x elements.
161
+
162
+   if (indAPI == s_APIInstances.end())
163
+       throw std::exception("Invalid API Index");
164
+
165
+   return indAPI->get()->GetName();
166
 }
167
 
168
-Plugin::API::APIType Plugin::API::APIBase::GetType() {
169
-   return myType;
170
+
171
+std::shared_ptr<Base> Plugin::API::Base::GetAPIByName(std::string name) {
172
+   for (auto api : s_APIInstances) {
173
+       if (name == api->GetName()) {
174
+           return api;
175
+       }
176
+   }
177
+   // If none was found, return the first one.
178
+   return *s_APIInstances.begin();
179
 }
180
 
181
-void* Plugin::API::APIBase::GetContext() {
182
-   return nullptr;
183
+std::vector<std::shared_ptr<Base>> Plugin::API::Base::EnumerateAPIs() {
184
+   return std::vector<std::shared_ptr<Base>>(s_APIInstances);
185
 }
186
 
187
-Plugin::API::Device Plugin::API::APIBase::GetDevice() {
188
-   return myDevice;
189
+std::vector<std::string> Plugin::API::Base::EnumerateAPINames() {
190
+   std::vector<std::string> names;
191
+   for (auto api : s_APIInstances) {
192
+       names.push_back(api->GetName());
193
+   }
194
+   return names;
195
 }
196
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Source/api-d3d11.cpp -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/api-d3d11.cpp Changed
397
 
1
@@ -22,7 +22,6 @@
2
 SOFTWARE.
3
 */
4
 
5
-#ifdef _WIN32
6
 //////////////////////////////////////////////////////////////////////////
7
 // Includes
8
 //////////////////////////////////////////////////////////////////////////
9
@@ -32,11 +31,11 @@
10
 #include <string>
11
 #include <sstream>
12
 #include <stdlib.h>
13
+#include <mutex>
14
 
15
 #include <dxgi.h>
16
 #include <d3d11.h>
17
-
18
-#include <mutex>
19
+#include <atlutil.h>
20
 
21
 //////////////////////////////////////////////////////////////////////////
22
 // Code
23
@@ -67,6 +66,18 @@
24
            FreeLibrary(hModule);
25
    }
26
 
27
+   HRESULT CreateDXGIFactory(REFIID riid, _Out_ void **ppFactory) {
28
+       if (hModule == 0)
29
+           return S_FALSE;
30
+
31
+       typedef HRESULT(__stdcall *t_CreateDXGIFactory)(REFIID, void**);
32
+       t_CreateDXGIFactory pCreateDXGIFactory = (t_CreateDXGIFactory)GetProcAddress(hModule, "CreateDXGIFactory");
33
+
34
+       if (pCreateDXGIFactory) {
35
+           return pCreateDXGIFactory(riid, ppFactory);
36
+       }
37
+       return S_FALSE;
38
+   }
39
    HRESULT CreateDXGIFactory1(REFIID riid, _Out_ void **ppFactory) {
40
        if (hModule == 0)
41
            return S_FALSE;
42
@@ -83,6 +94,7 @@
43
    private:
44
    HMODULE hModule;
45
 };
46
+
47
 class SingletonD3D11 {
48
    public:
49
 
50
@@ -138,174 +150,208 @@
51
    HMODULE hModule;
52
 };
53
 
54
-Plugin::API::Device BuildDeviceFromAdapter(DXGI_ADAPTER_DESC1* pAdapter) {
55
-   if (pAdapter == nullptr)
56
-       return Device("INVALID DEVICE", "");
57
-
58
-   std::vector<char> uidBuf(1024);
59
-   sprintf(uidBuf.data(), "%ld:%ld",
60
-       pAdapter->AdapterLuid.LowPart,
61
-       pAdapter->AdapterLuid.HighPart);
62
-
63
-   std::vector<char> nameBuf(1024);
64
-   wcstombs(nameBuf.data(), pAdapter->Description, 1024);
65
-
66
-   return Device(std::string(nameBuf.data()), std::string(uidBuf.data()));
67
+std::string Plugin::API::Direct3D11::GetName() {
68
+   return std::string("Direct3D 11");
69
 }
70
 
71
-std::vector<Plugin::API::Device> Plugin::API::Direct3D11::EnumerateDevices() {
72
-   std::vector<Plugin::API::Device> devices = std::vector<Plugin::API::Device>();
73
-
74
-   IDXGIFactory1* pFactory = NULL;
75
-   auto singletonDXGI = SingletonDXGI::GetInstance();
76
-   HRESULT hr = singletonDXGI->CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pFactory));
77
-   if (FAILED(hr)) {
78
-       return devices;
79
+std::vector<Adapter> Plugin::API::Direct3D11::EnumerateAdapters() {
80
+   auto dxgiInst = SingletonDXGI::GetInstance();
81
+
82
+   ATL::CComPtr<IDXGIFactory1> dxgiFactory;
83
+   HRESULT hr = dxgiInst->CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&dxgiFactory);
84
+   if (FAILED(hr))
85
+       throw std::exception("<" __FUNCTION_NAME__ "> Failed to enumerate adapters, error code %X.", hr);
86
+
87
+   std::vector<Adapter> adapters;
88
+   IDXGIAdapter1* dxgiAdapter = nullptr;
89
+   for (size_t adapterIndex = 0;
90
+       !FAILED(dxgiFactory->EnumAdapters1((UINT)adapterIndex, &dxgiAdapter));
91
+       adapterIndex++) {
92
+       DXGI_ADAPTER_DESC1 desc = DXGI_ADAPTER_DESC1();
93
+       dxgiAdapter->GetDesc1(&desc);
94
+
95
+       if (desc.VendorId != 0x1002 /* AMD */)
96
+           continue;
97
+
98
+       std::vector<char> descBuf(256);
99
+       wcstombs(descBuf.data(), desc.Description, descBuf.size());
100
+       adapters.push_back(Adapter(
101
+           desc.AdapterLuid.LowPart,
102
+           desc.AdapterLuid.HighPart,
103
+           std::string(descBuf.data())
104
+       ));
105
    }
106
 
107
-   IDXGIAdapter1* pAdapter = NULL;
108
-   for (uint32_t iAdapterIndex = 0; pFactory->EnumAdapters1(iAdapterIndex, &pAdapter) != DXGI_ERROR_NOT_FOUND; iAdapterIndex++) {
109
-       DXGI_ADAPTER_DESC1 adapterDesc = DXGI_ADAPTER_DESC1();
110
-       std::memset(&adapterDesc, 0, sizeof(DXGI_ADAPTER_DESC1));
111
+   return adapters;
112
+}
113
 
114
-       if (pAdapter->GetDesc1(&adapterDesc) == S_OK) {
115
-           // Only allow AMD devices to be listed here.
116
-           if (adapterDesc.VendorId != 0x1002)
117
-               continue;
118
+Plugin::API::Adapter Plugin::API::Direct3D11::GetAdapterById(uint32_t idLow, uint32_t idHigh) {
119
+   for (auto adapter : EnumerateAdapters()) {
120
+       if ((adapter.idLow == idLow) && (adapter.idHigh == idHigh))
121
+           return adapter;
122
+   }
123
+   return *(EnumerateAdapters().begin());
124
+}
125
 
126
-           devices.push_back(BuildDeviceFromAdapter(&adapterDesc));
127
-       }
128
+Plugin::API::Adapter Plugin::API::Direct3D11::GetAdapterByName(std::string name) {
129
+   for (auto adapter : EnumerateAdapters()) {
130
+       if (adapter.Name == name)
131
+           return adapter;
132
    }
133
+   return *(EnumerateAdapters().begin());
134
+}
135
 
136
-   pFactory->Release();
137
+struct Direct3D11Instance {
138
+   ATL::CComPtr<IDXGIFactory1> factory;
139
+   ATL::CComPtr<ID3D11Device> device;
140
+   ATL::CComPtr<ID3D11DeviceContext> context;
141
+};
142
 
143
-   return devices;
144
-}
145
+void* Plugin::API::Direct3D11::CreateInstanceOnAdapter(Adapter adapter) {
146
+   HRESULT hr;
147
 
148
-Plugin::API::Device Plugin::API::Direct3D11::GetDeviceForUniqueId(std::string uniqueId) {
149
-   Plugin::API::Device device = Device("", "");
150
+   auto dxgiInst = SingletonDXGI::GetInstance();
151
 
152
-   IDXGIFactory1* pFactory = NULL;
153
-   auto singletonDXGI = SingletonDXGI::GetInstance();
154
-   HRESULT hr = singletonDXGI->CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pFactory));
155
+   ATL::CComPtr<IDXGIFactory1> dxgiFactory;
156
+   hr = dxgiInst->CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&dxgiFactory);
157
    if (FAILED(hr)) {
158
-       return device;
159
+       std::vector<char> buf(1024);
160
+       std::sprintf(buf.data(), "<" __FUNCTION_NAME__ "> Failed to enumerate adapters, error code %X.", hr);
161
+       throw std::exception(buf.data());
162
    }
163
 
164
-   IDXGIAdapter1* pAdapter = NULL;
165
-   for (uint32_t iAdapterIndex = 0; pFactory->EnumAdapters1(iAdapterIndex, &pAdapter) != DXGI_ERROR_NOT_FOUND; iAdapterIndex++) {
166
-       DXGI_ADAPTER_DESC1 adapterDesc = DXGI_ADAPTER_DESC1();
167
-       std::memset(&adapterDesc, 0, sizeof(DXGI_ADAPTER_DESC1));
168
-
169
-       if (pAdapter->GetDesc1(&adapterDesc) == S_OK) {
170
-           // Only allow AMD devices to be listed here.
171
-           if (adapterDesc.VendorId != 0x1002)
172
-               continue;
173
-
174
-           Plugin::API::Device device2 = BuildDeviceFromAdapter(&adapterDesc);
175
-
176
-           if (uniqueId == device2.UniqueId) {
177
-               device = device2;
178
+   LUID adapterLUID;
179
+   adapterLUID.LowPart = adapter.idLow;
180
+   adapterLUID.HighPart = adapter.idHigh;
181
+
182
+   ATL::CComPtr<IDXGIAdapter> dxgiAdapter;
183
+   for (size_t adapterIndex = 0;
184
+       !FAILED(dxgiFactory->EnumAdapters((UINT)adapterIndex, &dxgiAdapter));
185
+       adapterIndex++) {
186
+       DXGI_ADAPTER_DESC desc = DXGI_ADAPTER_DESC();
187
+       dxgiAdapter->GetDesc(&desc);
188
+
189
+       if (desc.VendorId != 0x1002 /* AMD */)
190
+           continue;
191
+
192
+       if ((desc.AdapterLuid.HighPart == adapterLUID.HighPart)
193
+           && (desc.AdapterLuid.LowPart == adapterLUID.LowPart)) {
194
+           hr = NOERROR;
195
+           break;
196
+       } else {
197
+           hr = E_INVALIDARG;
198
+       }
199
+   }
200
+   if (FAILED(hr))
201
+       throw std::invalid_argument("adapter");
202
+
203
+   // Create D3D Stuff
204
+   auto d3dInst = SingletonD3D11::GetInstance();
205
+   D3D_FEATURE_LEVEL featureLevels[] = {
206
+       D3D_FEATURE_LEVEL_11_1,
207
+       D3D_FEATURE_LEVEL_11_0
208
+   };
209
+   ID3D11Device* d3dDevice;
210
+   ID3D11DeviceContext* d3dContext;
211
+   for (size_t c = 0; c < 3; c++) {
212
+       uint32_t flags = 0;
213
+
214
+       switch (c) {
215
+           case 0:
216
+               flags |= D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
217
+           case 1:
218
+               flags |= D3D11_CREATE_DEVICE_BGRA_SUPPORT;
219
+           case 2:
220
                break;
221
-           }
222
        }
223
+
224
+       hr = d3dInst->D3D11CreateDevice(
225
+           dxgiAdapter,
226
+           dxgiAdapter == NULL ? D3D_DRIVER_TYPE_HARDWARE : D3D_DRIVER_TYPE_UNKNOWN,
227
+           NULL,
228
+           flags,
229
+           featureLevels + 1, _countof(featureLevels) - 1,
230
+           D3D11_SDK_VERSION,
231
+           &d3dDevice,
232
+           NULL,
233
+           &d3dContext);
234
+       if (SUCCEEDED(hr)) {
235
+           break;
236
+       } else {
237
+           AMF_LOG_WARNING("<" __FUNCTION_NAME__ "> Unable to create D3D11 device, error code %X (mode %d).", hr, c);
238
+       }
239
+   }
240
+   if (FAILED(hr)) {
241
+       std::vector<char> buf(1024);
242
+       std::sprintf(buf.data(), "<" __FUNCTION_NAME__ "> Unable to create D3D11 device, error code %X.", hr);
243
+       throw std::exception(buf.data());
244
    }
245
 
246
-   pFactory->Release();
247
-   return device;
248
+   Direct3D11Instance* instance = new Direct3D11Instance();
249
+   instance->factory = dxgiFactory;
250
+   instance->device = d3dDevice;
251
+   instance->context = d3dContext;
252
+   return instance;
253
 }
254
 
255
-Plugin::API::Direct3D11::Direct3D11(Device device) : APIBase(device) {
256
-   IDXGIFactory1 *pFactory;
257
+Plugin::API::Adapter Plugin::API::Direct3D11::GetAdapterForInstance(void* pInstance) {
258
+   HRESULT hr;
259
 
260
-   this->myType = APIType_Direct3D11;
261
+   if (pInstance == nullptr)
262
+       throw std::invalid_argument("instance");
263
 
264
-   auto singletonDXGI = SingletonDXGI::GetInstance();
265
-   if (FAILED(singletonDXGI->CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pFactory))))
266
-       throw new std::exception("Unable to create D3D11 driver.");
267
+   Direct3D11Instance* instance = static_cast<Direct3D11Instance*>(pInstance);
268
+   if (instance == nullptr)
269
+       throw std::invalid_argument("instance");
270
+
271
+   ATL::CComPtr<IDXGIAdapter> dxgiAdapter;
272
+   hr = instance->device->QueryInterface(&dxgiAdapter);
273
+   if (FAILED(hr)) {
274
+       std::vector<char> buf(1024);
275
+       std::sprintf(buf.data(), "<" __FUNCTION_NAME__ "> Failed to query Adapter from D3D11 device, error code %X.", hr);
276
+       throw std::exception(buf.data());
277
+   }
278
 
279
-   try {
280
-       IDXGIAdapter1 *pAdapter = NULL;
281
-       if (device.UniqueId != "") {
282
-           IDXGIAdapter1 *pAdapter2 = NULL;
283
-           for (uint32_t iAdapterIndex = 0; pFactory->EnumAdapters1(iAdapterIndex, &pAdapter2) != DXGI_ERROR_NOT_FOUND; iAdapterIndex++) {
284
-               DXGI_ADAPTER_DESC1 adapterDesc = DXGI_ADAPTER_DESC1();
285
-               std::memset(&adapterDesc, 0, sizeof(DXGI_ADAPTER_DESC1));
286
+   DXGI_ADAPTER_DESC adapterDesc;
287
+   hr = dxgiAdapter->GetDesc(&adapterDesc);
288
+   if (FAILED(hr)) {
289
+       std::vector<char> buf(1024);
290
+       std::sprintf(buf.data(), "<" __FUNCTION_NAME__ "> Failed to get description from DXGI adapter, error code %X.", hr);
291
+       throw std::exception(buf.data());
292
+   }
293
 
294
-               if (pAdapter2->GetDesc1(&adapterDesc) == S_OK) {
295
-                   // Only allow AMD devices to be listed here.
296
-                   if (adapterDesc.VendorId != 0x1002)
297
-                       continue;
298
+   std::vector<char> descBuf(256);
299
+   wcstombs(descBuf.data(), adapterDesc.Description, descBuf.size());
300
 
301
-                   Plugin::API::Device device2 = BuildDeviceFromAdapter(&adapterDesc);
302
+   return Adapter(
303
+       adapterDesc.AdapterLuid.LowPart,
304
+       adapterDesc.AdapterLuid.HighPart,
305
+       std::string(descBuf.data())
306
+   );
307
+}
308
 
309
-                   if (device.UniqueId == device2.UniqueId) {
310
-                       pAdapter = pAdapter2;
311
-                       break;
312
-                   }
313
-               }
314
-           }
315
-       }
316
+void* Plugin::API::Direct3D11::GetContextFromInstance(void* pInstance) {
317
+   if (pInstance == nullptr)
318
+       throw std::invalid_argument("instance");
319
 
320
-       try {
321
-           D3D_FEATURE_LEVEL featureLevels[] = {
322
-               D3D_FEATURE_LEVEL_11_1,
323
-               D3D_FEATURE_LEVEL_11_0
324
-           };
325
-           D3D_FEATURE_LEVEL featureLevel;
326
-           uint32_t flags =
327
-               D3D11_CREATE_DEVICE_BGRA_SUPPORT |
328
-               D3D11_CREATE_DEVICE_DISABLE_GPU_TIMEOUT |
329
-               D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
330
-
331
-           DXGI_ADAPTER_DESC desc;
332
-           if (pAdapter != NULL) {
333
-               pAdapter->GetDesc(&desc);
334
-           }
335
-
336
-           auto singletonD3D11 = SingletonD3D11::GetInstance();
337
-           HRESULT hr = singletonD3D11->D3D11CreateDevice(
338
-               pAdapter, pAdapter == NULL ? D3D_DRIVER_TYPE_HARDWARE : D3D_DRIVER_TYPE_UNKNOWN,
339
-               NULL, flags,
340
-               featureLevels, _countof(featureLevels),
341
-               D3D11_SDK_VERSION,
342
-               &pDevice, &featureLevel, &pDeviceContext);
343
-           if (FAILED(hr)) {
344
-               AMF_LOG_ERROR("Unable to create D3D11.1 device.");
345
-               hr = singletonD3D11->D3D11CreateDevice(
346
-                   pAdapter, pAdapter == NULL ? D3D_DRIVER_TYPE_HARDWARE : D3D_DRIVER_TYPE_UNKNOWN,
347
-                   NULL, flags,
348
-                   featureLevels + 1, _countof(featureLevels) - 1,
349
-                   D3D11_SDK_VERSION,
350
-                   &pDevice, &featureLevel, &pDeviceContext);
351
-               if (FAILED(hr)) {
352
-                   throw std::exception("Unable to create D3D11 device.");
353
-               }
354
-           }
355
-       } catch (...) {
356
-           if (pAdapter)
357
-               pAdapter->Release();
358
-
359
-           throw;
360
-       }
361
-   } catch (...) {
362
-       if (pFactory)
363
-           pFactory->Release();
364
+   Direct3D11Instance* instance = static_cast<Direct3D11Instance*>(pInstance);
365
+   if (instance == nullptr)
366
+       throw std::invalid_argument("instance");
367
 
368
-       throw;
369
-   }
370
+   return instance->device;
371
 }
372
 
373
-Plugin::API::Direct3D11::~Direct3D11() {
374
-   if (pDeviceContext)
375
-       pDeviceContext->Release();
376
-   if (pDevice)
377
-       pDevice->Release();
378
-}
379
+void Plugin::API::Direct3D11::DestroyInstance(void* pInstance) {
380
+   if (pInstance == nullptr)
381
+       throw std::invalid_argument("instance");
382
 
383
-void* Plugin::API::Direct3D11::GetContext() {
384
-   return pDevice;
385
-}
386
+   Direct3D11Instance* instance = static_cast<Direct3D11Instance*>(pInstance);
387
+   if (instance == nullptr)
388
+       throw std::invalid_argument("instance");
389
 
390
+   delete instance;
391
+}
392
 
393
-#endif
394
+Plugin::API::APIType Plugin::API::Direct3D11::GetType() {
395
+   return APIType_Direct3D11;
396
+}
397
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Source/api-d3d9.cpp -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/api-d3d9.cpp Changed
351
 
1
@@ -22,179 +22,220 @@
2
 SOFTWARE.
3
 */
4
 
5
-#ifdef _WIN32
6
 //////////////////////////////////////////////////////////////////////////
7
 // Includes
8
 //////////////////////////////////////////////////////////////////////////
9
 #include "api-d3d9.h"
10
 
11
+#include <mutex>
12
+#include <list>
13
+
14
+#ifdef _DEBUG
15
+#define D3D_DEBUG_INFO
16
+#endif
17
+#pragma comment(lib, "d3d9.lib")
18
+#include <d3d9.h>
19
+#include <atlutil.h>
20
+
21
 //////////////////////////////////////////////////////////////////////////
22
 // Code
23
 //////////////////////////////////////////////////////////////////////////
24
 using namespace Plugin::API;
25
 
26
-Plugin::API::Device BuildDeviceFromAdapter(D3DADAPTER_IDENTIFIER9* pAdapter) {
27
-   if (pAdapter == nullptr)
28
-       return Device("INVALID DEVICE", "");
29
-
30
-   std::vector<char> uidBuf(1024);
31
-   sprintf(uidBuf.data(), "%ld:%ld:%ld:%ld",
32
-       pAdapter->VendorId,
33
-       pAdapter->DeviceId,
34
-       pAdapter->SubSysId,
35
-       pAdapter->Revision);
36
-
37
-   std::vector<char> nameBuf(1024);
38
-   sprintf(nameBuf.data(), "%s (%s)",
39
-       pAdapter->DeviceName,
40
-       pAdapter->Description);
41
-
42
-   return Device(std::string(nameBuf.data()), std::string(uidBuf.data()));
43
+std::string Plugin::API::Direct3D9::GetName() {
44
+   return std::string("Direct3D 9");
45
 }
46
 
47
+std::vector<Adapter> Plugin::API::Direct3D9::EnumerateAdapters() {
48
+   ATL::CComPtr<IDirect3D9Ex> pD3DEx;
49
+   HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &pD3DEx);
50
+   if (FAILED(hr))
51
+       throw std::exception("<" __FUNCTION_NAME__ "> Failed to enumerate adapters, error code %X.", hr);
52
 
53
-std::vector<Plugin::API::Device> Plugin::API::Direct3D9::EnumerateDevices() {
54
-   std::vector<Plugin::API::Device> devices = std::vector<Plugin::API::Device>();
55
+   std::vector<Adapter> adapters;
56
+   std::list<LUID> enumeratedLUIDs;
57
+   D3DADAPTER_IDENTIFIER9 adapterIdentifier;
58
+   for (size_t adapterIndex = 0;
59
+       !FAILED(pD3DEx->GetAdapterIdentifier((UINT)adapterIndex, 0, &adapterIdentifier));
60
+       adapterIndex++) {
61
 
62
-   IDirect3D9* pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);
63
+       if (adapterIdentifier.VendorId != 0x1002 /* AMD */)
64
+           continue;
65
 
66
-   uint32_t adapterCount = pDirect3D->GetAdapterCount();
67
-   for (uint32_t adapterIndex = 0; adapterIndex < adapterCount; adapterIndex++) {
68
-       D3DADAPTER_IDENTIFIER9 adapterDesc = D3DADAPTER_IDENTIFIER9();
69
-       pDirect3D->GetAdapterIdentifier(adapterIndex, 0, &adapterDesc);
70
+       LUID adapterLUID;
71
+       if (FAILED(pD3DEx->GetAdapterLUID((UINT)adapterIndex, &adapterLUID)))
72
+           continue;
73
 
74
-       if (adapterDesc.VendorId != 0x1002)
75
+       bool enumerated = false;
76
+       for (LUID enumeratedLUID : enumeratedLUIDs) {
77
+           if ((enumeratedLUID.LowPart == adapterLUID.LowPart)
78
+               && (enumeratedLUID.HighPart == adapterLUID.HighPart)) {
79
+               enumerated = true;
80
+               break;
81
+           }
82
+       }
83
+       if (enumerated)
84
            continue;
85
+       else
86
+           enumeratedLUIDs.push_back(adapterLUID);
87
 
88
-       Device device = BuildDeviceFromAdapter(&adapterDesc);
89
-       devices.push_back(device);
90
+       adapters.emplace_back(
91
+           Adapter(adapterLUID.LowPart, adapterLUID.HighPart,
92
+               std::string(adapterIdentifier.Description)));
93
    }
94
 
95
-   pDirect3D->Release();
96
-
97
-   return devices;
98
+   return adapters;
99
 }
100
 
101
-Plugin::API::Device Plugin::API::Direct3D9::GetDeviceForUniqueId(std::string uniqueId) {
102
-   Plugin::API::Device device = Device("", "");
103
-
104
-   IDirect3D9* pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);
105
-
106
-   uint32_t adapterCount = pDirect3D->GetAdapterCount();
107
-   for (uint32_t adapterIndex = 0; adapterIndex <= adapterCount; adapterIndex++) {
108
-       D3DADAPTER_IDENTIFIER9 adapterDesc = D3DADAPTER_IDENTIFIER9();
109
-       pDirect3D->GetAdapterIdentifier(adapterIndex, 0, &adapterDesc);
110
-
111
-       if (adapterDesc.VendorId != 0x1002)
112
-           continue;
113
-
114
-       Device device2 = BuildDeviceFromAdapter(&adapterDesc);
115
-       if (device2.UniqueId == uniqueId)
116
-           device = device2;
117
+Plugin::API::Adapter Plugin::API::Direct3D9::GetAdapterById(uint32_t idLow, uint32_t idHigh) {
118
+   for (auto adapter : EnumerateAdapters()) {
119
+       if ((adapter.idLow == idLow) && (adapter.idHigh == idHigh))
120
+           return adapter;
121
    }
122
+   return *(EnumerateAdapters().begin());
123
+}
124
 
125
-   pDirect3D->Release();
126
-
127
-   return device;
128
+Plugin::API::Adapter Plugin::API::Direct3D9::GetAdapterByName(std::string name) {
129
+   for (auto adapter : EnumerateAdapters()) {
130
+       if (adapter.Name == name)
131
+           return adapter;
132
+   }
133
+   return *(EnumerateAdapters().begin());
134
 }
135
 
136
-struct EnumWindowsData {
137
-   DWORD processId;
138
-   HWND bestWindowId;
139
+struct Direct3D9Instance {
140
+   ATL::CComPtr<IDirect3D9Ex> d3d;
141
+   ATL::CComPtr<IDirect3DDevice9Ex> device;
142
 };
143
 
144
-BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam) {
145
-   EnumWindowsData* data = (EnumWindowsData*)lParam;
146
-
147
-   DWORD processId;
148
-   GetWindowThreadProcessId(handle, &processId);
149
-   if ((processId == data->processId)
150
-       && (GetWindow(handle, GW_OWNER) == (HWND)0)
151
-       && (IsWindowVisible(handle))) {
152
-       return TRUE;
153
+void* Plugin::API::Direct3D9::CreateInstanceOnAdapter(Adapter adapter) {
154
+   ATL::CComPtr<IDirect3D9Ex> pD3DEx;
155
+   HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &pD3DEx);
156
+   if (FAILED(hr)) {
157
+       std::vector<char> buf(1024);
158
+       std::sprintf(buf.data(), "<" __FUNCTION_NAME__ "> Unable to create Direct3D 9 instance, error code %X.", hr);
159
+       throw std::exception(buf.data());
160
    }
161
-   data->bestWindowId = handle;
162
-   return FALSE;
163
-}
164
-
165
-Plugin::API::Direct3D9::Direct3D9(Device device) : APIBase(device) {
166
-   this->myType = APIType_Direct3D9;
167
 
168
-   pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);
169
-   if (!pDirect3D)
170
-       throw std::exception("Unable to create D3D9 driver.");
171
+   size_t adapterNum = (size_t)-1;
172
+   D3DADAPTER_IDENTIFIER9 adapterIdentifier;
173
+   for (size_t adapterIndex = 0;
174
+       !FAILED(pD3DEx->GetAdapterIdentifier((UINT)adapterIndex, 0, &adapterIdentifier));
175
+       adapterIndex++) {
176
 
177
-   // Find Adapter Index
178
-   uint32_t usedAdapter = 0;
179
-   uint32_t adapterCount = pDirect3D->GetAdapterCount();
180
-   for (uint32_t adapterIndex = 0; adapterIndex <= adapterCount; adapterIndex++) {
181
-       D3DADAPTER_IDENTIFIER9 adapterDesc = D3DADAPTER_IDENTIFIER9();
182
-       pDirect3D->GetAdapterIdentifier(adapterIndex, 0, &adapterDesc);
183
+       if (adapterIdentifier.VendorId != 0x1002 /* AMD */)
184
+           continue;
185
 
186
-       if (adapterDesc.VendorId != 0x1002)
187
+       LUID adapterLUID;
188
+       if (FAILED(pD3DEx->GetAdapterLUID((UINT)adapterIndex, &adapterLUID)))
189
            continue;
190
 
191
-       Device device2 = BuildDeviceFromAdapter(&adapterDesc);
192
-       if (device2.UniqueId == device.UniqueId) {
193
-           usedAdapter = adapterIndex++;
194
+       if ((adapterLUID.LowPart == adapter.idLow)
195
+           && (adapterLUID.HighPart == adapter.idHigh)) {
196
+           adapterNum = adapterIndex;
197
            break;
198
        }
199
    }
200
+   if (adapterNum == -1)
201
+       throw std::invalid_argument("adapter");
202
+
203
+   D3DPRESENT_PARAMETERS presentParameters;
204
+   std::memset(&presentParameters, 0, sizeof(D3DPRESENT_PARAMETERS));
205
+   presentParameters.BackBufferWidth = 0;
206
+   presentParameters.BackBufferHeight = 0;
207
+   presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
208
+   presentParameters.Windowed = TRUE;
209
+   presentParameters.SwapEffect = D3DSWAPEFFECT_COPY;
210
+   presentParameters.hDeviceWindow = GetDesktopWindow();
211
+   presentParameters.Flags = D3DPRESENTFLAG_VIDEO;
212
+   presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
213
+
214
+   D3DCAPS9    ddCaps;
215
+   std::memset(&ddCaps, 0, sizeof(ddCaps));
216
+   hr = pD3DEx->GetDeviceCaps((UINT)adapterNum, D3DDEVTYPE_HAL, &ddCaps);
217
+   if (FAILED(hr)) {
218
+       std::vector<char> buf(1024);
219
+       std::sprintf(buf.data(), "<" __FUNCTION_NAME__ "> Unable to query capabilities for D3D9 adapter, error code %X.", hr);
220
+       throw std::exception(buf.data());
221
+   }
222
+
223
+   DWORD       vp = 0;
224
+   if (ddCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) {
225
+       vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
226
+   } else {
227
+       vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
228
+   }
229
 
230
-   EnumWindowsData data = EnumWindowsData();
231
-   data.processId = GetCurrentProcessId();
232
-   EnumWindows(EnumWindowsCallback, (LPARAM)&data);
233
-
234
-   D3DPRESENT_PARAMETERS pPresentParameter = D3DPRESENT_PARAMETERS();
235
-   pPresentParameter.BackBufferWidth = 1280;
236
-   pPresentParameter.BackBufferHeight = 720;
237
-   pPresentParameter.BackBufferFormat = D3DFORMAT::D3DFMT_X8R8G8B8;
238
-   pPresentParameter.BackBufferCount = 2;
239
-   pPresentParameter.MultiSampleType = D3DMULTISAMPLE_TYPE::D3DMULTISAMPLE_NONE;
240
-   pPresentParameter.MultiSampleQuality = 0;
241
-   pPresentParameter.SwapEffect = D3DSWAPEFFECT::D3DSWAPEFFECT_DISCARD;
242
-   pPresentParameter.hDeviceWindow = data.bestWindowId;
243
-   pPresentParameter.Windowed = TRUE;
244
-   pPresentParameter.EnableAutoDepthStencil = FALSE;
245
-   pPresentParameter.AutoDepthStencilFormat = D3DFORMAT::D3DFMT_A1;
246
-   pPresentParameter.Flags = D3DPRESENTFLAG_VIDEO;
247
-   pPresentParameter.FullScreen_RefreshRateInHz = 0;
248
-   pPresentParameter.PresentationInterval = 60;
249
-       
250
-   HRESULT hr = pDirect3D->CreateDevice(usedAdapter,
251
+   ATL::CComPtr<IDirect3DDevice9Ex> pD3DDeviceEx;
252
+   hr = pD3DEx->CreateDeviceEx(
253
+       (UINT)adapterNum,
254
        D3DDEVTYPE_HAL,
255
-       data.bestWindowId,
256
-       0, //D3DCREATE_DISABLE_DRIVER_MANAGEMENT_EX | D3DCREATE_MULTITHREADED | D3DCREATE_PUREDEVICE | D3DCREATE_MIXED_VERTEXPROCESSING | D3DCREATE_NOWINDOWCHANGES,
257
-       &pPresentParameter,
258
-       &pDirect3DDevice);
259
-   switch (hr) {
260
-       case D3DERR_DEVICELOST:
261
-           throw std::exception("D3DERR_DEVICELOST");
262
-           break;
263
-       case D3DERR_INVALIDCALL:
264
-           throw std::exception("D3DERR_INVALIDCALL");
265
-           break;
266
-       case D3DERR_NOTAVAILABLE:
267
-           throw std::exception("D3DERR_NOTAVAILABLE");
268
-           break;
269
-       case D3DERR_OUTOFVIDEOMEMORY:
270
-           throw std::exception("D3DERR_OUTOFVIDEOMEMORY");
271
-           break;
272
+       presentParameters.hDeviceWindow,
273
+       vp | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED,
274
+       &presentParameters,
275
+       NULL,
276
+       &pD3DDeviceEx
277
+   );
278
+   if (FAILED(hr)) {
279
+       std::vector<char> buf(1024);
280
+       std::sprintf(buf.data(), "<" __FUNCTION_NAME__ "> Unable to create D3D9 device, error code %X.", hr);
281
+       throw std::exception(buf.data());
282
    }
283
-   if (FAILED(hr))
284
-       throw std::exception("Unable to create D3D9 device.");
285
+
286
+   Direct3D9Instance* instance = new Direct3D9Instance();
287
+   instance->d3d = pD3DEx;
288
+   instance->device = pD3DDeviceEx;
289
+   return instance;
290
 }
291
 
292
-Plugin::API::Direct3D9::~Direct3D9() {
293
-   if (pDirect3DDevice)
294
-       pDirect3DDevice->Release();
295
+Plugin::API::Adapter Plugin::API::Direct3D9::GetAdapterForInstance(void* pInstance) {
296
+   if (pInstance == nullptr)
297
+       throw std::invalid_argument("instance");
298
+
299
+   Direct3D9Instance* instance = static_cast<Direct3D9Instance*>(pInstance);
300
+   if (instance == nullptr)
301
+       throw std::invalid_argument("instance");
302
 
303
-   if (pDirect3D)
304
-       pDirect3D->Release();
305
+   D3DDEVICE_CREATION_PARAMETERS par;
306
+   HRESULT hr = instance->device->GetCreationParameters(&par);
307
+   if (FAILED(hr)) {
308
+       std::vector<char> buf(1024);
309
+       std::sprintf(buf.data(), "<" __FUNCTION_NAME__ "> Unable to get adapter from D3D9 device, error code %X.", hr);
310
+       throw std::exception(buf.data());
311
+   }
312
+
313
+   auto adapters = Direct3D9::EnumerateAdapters();
314
+   if (par.AdapterOrdinal > adapters.size())
315
+       return *adapters.begin();
316
+   
317
+   auto adapter = adapters.begin();
318
+   for (size_t n = 0; n < par.AdapterOrdinal; n++)
319
+       adapter++;
320
+   return *adapter;    
321
 }
322
 
323
-void* Plugin::API::Direct3D9::GetContext() {
324
-   return pDirect3DDevice;
325
+void* Plugin::API::Direct3D9::GetContextFromInstance(void* pInstance) {
326
+   if (pInstance == nullptr)
327
+       throw std::invalid_argument("instance");
328
+
329
+   Direct3D9Instance* instance = static_cast<Direct3D9Instance*>(pInstance);
330
+   if (instance == nullptr)
331
+       throw std::invalid_argument("instance");
332
+
333
+   return instance->device;
334
 }
335
 
336
-#endif
337
+void Plugin::API::Direct3D9::DestroyInstance(void* pInstance) {
338
+   if (pInstance == nullptr)
339
+       throw std::invalid_argument("instance");
340
+
341
+   Direct3D9Instance* instance = static_cast<Direct3D9Instance*>(pInstance);
342
+   if (instance == nullptr)
343
+       throw std::invalid_argument("instance");
344
+
345
+   delete instance;
346
+}
347
+
348
+Plugin::API::APIType Plugin::API::Direct3D9::GetType() {
349
+   return APIType_Direct3D9;
350
+}
351
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/api-host.cpp Added
71
 
1
@@ -0,0 +1,69 @@
2
+/*
3
+MIT License
4
+
5
+Copyright (c) 2016 Michael Fabian Dirks
6
+
7
+Permission is hereby granted, free of charge, to any person obtaining a copy
8
+of this software and associated documentation files (the "Software"), to deal
9
+in the Software without restriction, including without limitation the rights
10
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+copies of the Software, and to permit persons to whom the Software is
12
+furnished to do so, subject to the following conditions:
13
+
14
+The above copyright notice and this permission notice shall be included in all
15
+copies or substantial portions of the Software.
16
+
17
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+SOFTWARE.
24
+*/
25
+
26
+//////////////////////////////////////////////////////////////////////////
27
+// Includes
28
+//////////////////////////////////////////////////////////////////////////
29
+#include "api-host.h"
30
+
31
+//////////////////////////////////////////////////////////////////////////
32
+// Code
33
+//////////////////////////////////////////////////////////////////////////
34
+using namespace Plugin::API;
35
+
36
+std::string Plugin::API::Host::GetName() {
37
+   return "Host";
38
+}
39
+
40
+Plugin::API::APIType Plugin::API::Host::GetType() {
41
+   return APIType_Host;
42
+}
43
+
44
+std::vector<Adapter> Plugin::API::Host::EnumerateAdapters() {
45
+   std::vector<Adapter> list;
46
+   list.push_back(Adapter(0, 0, TEXT_T(AMF_UTIL_DEFAULT)));
47
+   return list;
48
+}
49
+
50
+Plugin::API::Adapter Plugin::API::Host::GetAdapterById(uint32_t idLow, uint32_t idHigh) {
51
+   return Adapter(0, 0, TEXT_T(AMF_UTIL_DEFAULT));
52
+}
53
+
54
+Plugin::API::Adapter Plugin::API::Host::GetAdapterByName(std::string name) {
55
+   return Adapter(0, 0, TEXT_T(AMF_UTIL_DEFAULT));
56
+}
57
+
58
+void* Plugin::API::Host::CreateInstanceOnAdapter(Adapter adapter) {
59
+   return nullptr;
60
+}
61
+
62
+Plugin::API::Adapter Plugin::API::Host::GetAdapterForInstance(void* pInstance) {
63
+   return Adapter(0, 0, TEXT_T(AMF_UTIL_DEFAULT));
64
+}
65
+
66
+void* Plugin::API::Host::GetContextFromInstance(void* pInstance) {
67
+   throw std::exception("Host API does not have a Context.");
68
+}
69
+
70
+void Plugin::API::Host::DestroyInstance(void* pInstance) {}
71
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/api-opengl.cpp Added
88
 
1
@@ -0,0 +1,86 @@
2
+/*
3
+MIT License
4
+
5
+Copyright (c) 2016 Michael Fabian Dirks
6
+
7
+Permission is hereby granted, free of charge, to any person obtaining a copy
8
+of this software and associated documentation files (the "Software"), to deal
9
+in the Software without restriction, including without limitation the rights
10
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+copies of the Software, and to permit persons to whom the Software is
12
+furnished to do so, subject to the following conditions:
13
+
14
+The above copyright notice and this permission notice shall be included in all
15
+copies or substantial portions of the Software.
16
+
17
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+SOFTWARE.
24
+*/
25
+
26
+//////////////////////////////////////////////////////////////////////////
27
+// Includes
28
+//////////////////////////////////////////////////////////////////////////
29
+#include "api-opengl.h"
30
+
31
+#include <vector>
32
+
33
+#ifdef _WIN32
34
+#include <windows.h>
35
+#endif
36
+#include <gl/GL.h>
37
+
38
+//////////////////////////////////////////////////////////////////////////
39
+// Code
40
+//////////////////////////////////////////////////////////////////////////
41
+using namespace Plugin::API;
42
+
43
+std::string Plugin::API::OpenGL::GetName() {
44
+   return std::string("OpenGL");
45
+}
46
+
47
+std::vector<Adapter> Plugin::API::OpenGL::EnumerateAdapters() {
48
+   std::vector<Adapter> adapters;
49
+   adapters.push_back(Adapter(0, 0, "Default"));
50
+   return adapters;
51
+}
52
+
53
+Plugin::API::Adapter Plugin::API::OpenGL::GetAdapterById(uint32_t idLow, uint32_t idHigh) {
54
+   for (auto adapter : EnumerateAdapters()) {
55
+       if ((adapter.idLow == idLow) && (adapter.idHigh == idHigh))
56
+           return adapter;
57
+   }
58
+   return *(EnumerateAdapters().begin());
59
+}
60
+
61
+Plugin::API::Adapter Plugin::API::OpenGL::GetAdapterByName(std::string name) {
62
+   for (auto adapter : EnumerateAdapters()) {
63
+       if (adapter.Name == name)
64
+           return adapter;
65
+   }
66
+   return *(EnumerateAdapters().begin());
67
+}
68
+
69
+void* Plugin::API::OpenGL::CreateInstanceOnAdapter(Adapter adapter) {
70
+   return nullptr;
71
+}
72
+
73
+void Plugin::API::OpenGL::DestroyInstance(void* instance) {
74
+   return;
75
+}
76
+
77
+Plugin::API::Adapter Plugin::API::OpenGL::GetAdapterForInstance(void* instance) {
78
+   return *(EnumerateAdapters().begin());
79
+}
80
+
81
+void* Plugin::API::OpenGL::GetContextFromInstance(void* instance) {
82
+   return nullptr;
83
+}
84
+
85
+Plugin::API::APIType Plugin::API::OpenGL::GetType() {
86
+   return APIType_OpenGL;
87
+}
88
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Source/enc-h264.cpp -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/enc-h264.cpp Changed
1368
 
1
@@ -30,7 +30,7 @@
2
 #include "enc-h264.h"
3
 #include "misc-util.cpp"
4
 
5
-#if (defined _WIN32) || (defined _WIN64)
6
+#ifdef _WIN32
7
 #include <VersionHelpers.h>
8
 
9
 #include "api-d3d9.h"
10
@@ -62,15 +62,29 @@
11
 };
12
 
13
 void Plugin::Interface::H264Interface::encoder_register() {
14
-   static obs_encoder_info* encoder_info = new obs_encoder_info();
15
-   static const char* encoder_name = "amd_amf_h264";
16
-   static const char* encoder_codec = "h264";
17
+   // Ensure that there is a supported AMD GPU.
18
+   bool haveAVCsupport = false;
19
+   for (auto api : Plugin::API::Base::EnumerateAPIs()) {
20
+       for (auto adapter : api->EnumerateAdapters()) {
21
+           auto caps = VCECapabilities::GetInstance()->GetAdapterCapabilities(api, adapter, VCEEncoderType_AVC);
22
+           if (caps.acceleration_type != amf::AMF_ACCEL_NOT_SUPPORTED)
23
+               haveAVCsupport = true;
24
+       }
25
+   }
26
+   if (!haveAVCsupport) {
27
+       AMF_LOG_WARNING("No detected GPU supports H264 encoding.");
28
+       return;
29
+   }
30
 
31
-   std::memset(encoder_info, 0, sizeof(obs_encoder_info));
32
+   // Create structure
33
+   static std::unique_ptr<obs_encoder_info> encoder_info = std::make_unique<obs_encoder_info>();
34
+   std::memset(encoder_info.get(), 0, sizeof(obs_encoder_info));
35
 
36
    // Initialize Structure
37
-   encoder_info->id = encoder_name;
38
    encoder_info->type = obs_encoder_type::OBS_ENCODER_VIDEO;
39
+   static const char* encoder_name = "amd_amf_h264";
40
+   encoder_info->id = encoder_name;
41
+   static const char* encoder_codec = "h264";
42
    encoder_info->codec = encoder_codec;
43
 
44
    // Functions
45
@@ -84,7 +98,7 @@
46
    encoder_info->get_video_info = &get_video_info;
47
    encoder_info->get_extra_data = &get_extra_data;
48
 
49
-   obs_register_encoder(encoder_info);
50
+   obs_register_encoder(encoder_info.get());
51
 }
52
 
53
 const char* Plugin::Interface::H264Interface::get_name(void*) {
54
@@ -92,13 +106,6 @@
55
    return name;
56
 }
57
 
58
-//////////////////////////////////////////////////////////////////////////
59
-// Deprecated old Encoder
60
-const char* Plugin::Interface::H264Interface::get_name_simple(void*) {
61
-   static const char* name = "[DEPRECATED] H264 Encoder (AMD Advanced Media Framework)";
62
-   return name;
63
-}
64
-//////////////////////////////////////////////////////////////////////////
65
 void* Plugin::Interface::H264Interface::create(obs_data_t* settings, obs_encoder_t* encoder) {
66
    Plugin::Interface::H264Interface* enc = nullptr;
67
    try {
68
@@ -106,35 +113,33 @@
69
        enc = new Plugin::Interface::H264Interface(settings, encoder);
70
        return enc;
71
    } catch (std::exception e) {
72
-       AMF_LOG_ERROR("Exception: %s", e.what());
73
-       AMF_LOG_ERROR("Unable to create Encoder, see log for more information.");
74
-       if (enc)
75
-           delete enc;
76
-       return NULL;
77
+       AMF_LOG_ERROR("%s", e.what());
78
+   } catch (std::exception* e) {
79
+       AMF_LOG_ERROR("%s", e->what());
80
+       delete e;
81
    } catch (...) {
82
-       AMF_LOG_ERROR("Unhandled Exception during start up.");
83
-       if (enc)
84
-           delete enc;
85
-       return NULL;
86
+       AMF_LOG_ERROR("Unknown Exception during start up.");
87
    }
88
+   if (enc)
89
+       delete enc;
90
+   return NULL;
91
 }
92
 
93
-#pragma warning( push )
94
-#pragma warning( disable: 4702 )
95
 void Plugin::Interface::H264Interface::destroy(void* data) {
96
    try {
97
        AMF_LOG_INFO("Shutting down...");
98
        Plugin::Interface::H264Interface* enc = static_cast<Plugin::Interface::H264Interface*>(data);
99
        delete enc;
100
    } catch (std::exception e) {
101
-       AMF_LOG_ERROR("Exception: %s", e.what());
102
-       AMF_LOG_ERROR("Unable to destroy Encoder, see log for more information.");
103
+       AMF_LOG_ERROR("%s", e.what());
104
+   } catch (std::exception* e) {
105
+       AMF_LOG_ERROR("%s", e->what());
106
+       delete e;
107
    } catch (...) {
108
-       AMF_LOG_ERROR("Unhandled Exception during shut down.");
109
+       AMF_LOG_ERROR("Unknown Exception during shut down.");
110
    }
111
    data = nullptr;
112
 }
113
-#pragma warning( pop )
114
 
115
 bool Plugin::Interface::H264Interface::encode(void *data, struct encoder_frame *frame, struct encoder_packet *packet, bool *received_packet) {
116
    try {
117
@@ -150,7 +155,6 @@
118
 
119
 void Plugin::Interface::H264Interface::get_defaults(obs_data_t *data) {
120
    #pragma region OBS - Enforce Streaming Service Restrictions
121
-   // OBS - Enforce Streaming Service Restrictions
122
    obs_data_set_default_int(data, "bitrate", -1);
123
    obs_data_set_default_int(data, "keyint_sec", -1);
124
    obs_data_set_default_string(data, "rate_control", "");
125
@@ -163,14 +167,6 @@
126
    obs_data_set_string(data, "preset", "");
127
    #pragma endregion OBS - Enforce Streaming Service Restrictions
128
 
129
-   // Cached Data
130
-   obs_data_set_string(data, "last" vstr(AMF_H264_DEVICE), "InvalidUniqueDeviceId");
131
-   obs_data_set_int(data, "last" vstr(AMF_H264_VIEW), -1);
132
-   obs_data_set_int(data, "last" vstr(AMF_H264_RATECONTROLMETHOD), -1);
133
-   obs_data_set_int(data, "last" vstr(AMF_H264_VBVBUFFER), -1);
134
-   obs_data_set_int(data, "last" vstr(AMF_H264_BPICTURE_PATTERN), -1);
135
-   obs_data_set_int(data, "last" vstr(AMF_H264_BPICTURE_REFERENCE), -1);
136
-
137
    // Preset
138
    obs_data_set_default_int(data, AMF_H264_PRESET, -1);
139
 
140
@@ -179,10 +175,9 @@
141
    obs_data_set_default_int(data, AMF_H264_QUALITY_PRESET, VCEQualityPreset_Balanced);
142
    obs_data_set_default_int(data, AMF_H264_PROFILE, VCEProfile_Main);
143
    obs_data_set_default_int(data, AMF_H264_PROFILELEVEL, VCEProfileLevel_Automatic);
144
-   obs_data_set_default_int(data, AMF_H264_MAXIMUMLTRFRAMES, 0);
145
-   obs_data_set_default_int(data, AMF_H264_CODINGTYPE, 0);
146
 
147
    // Rate Control Properties
148
+   obs_data_set_int(data, "last" vstr(AMF_H264_RATECONTROLMETHOD), -1);
149
    obs_data_set_default_int(data, AMF_H264_RATECONTROLMETHOD, VCERateControlMethod_ConstantBitrate);
150
    obs_data_set_default_int(data, AMF_H264_BITRATE_TARGET, 3500);
151
    obs_data_set_default_int(data, AMF_H264_BITRATE_PEAK, 9000);
152
@@ -191,8 +186,7 @@
153
    obs_data_set_default_int(data, AMF_H264_QP_IFRAME, 22);
154
    obs_data_set_default_int(data, AMF_H264_QP_PFRAME, 22);
155
    obs_data_set_default_int(data, AMF_H264_QP_BFRAME, 22);
156
-   obs_data_set_default_int(data, AMF_H264_QP_BPICTURE_DELTA, 4);
157
-   obs_data_set_default_int(data, AMF_H264_QP_REFERENCE_BPICTURE_DELTA, 2);
158
+   obs_data_set_int(data, "last" vstr(AMF_H264_VBVBUFFER), -1);
159
    obs_data_set_default_int(data, AMF_H264_VBVBUFFER, 0);
160
    obs_data_set_default_int(data, AMF_H264_VBVBUFFER_SIZE, 3500);
161
    obs_data_set_default_double(data, AMF_H264_VBVBUFFER_STRICTNESS, 0);
162
@@ -200,38 +194,64 @@
163
    obs_data_set_default_int(data, AMF_H264_MAXIMUMACCESSUNITSIZE, 0);
164
    obs_data_set_default_int(data, AMF_H264_FILLERDATA, 1);
165
    obs_data_set_default_int(data, AMF_H264_FRAMESKIPPING, 0);
166
-   obs_data_set_default_int(data, AMF_H264_ENFORCEHRDCOMPATIBILITY, 0);
167
+   obs_data_set_default_int(data, AMF_H264_ENFORCEHRDCOMPATIBILITY, 1);
168
 
169
-   // Picture Control Properties
170
+   // Frame Control Properties
171
    obs_data_set_default_double(data, AMF_H264_KEYFRAME_INTERVAL, 2);
172
    obs_data_set_default_int(data, AMF_H264_IDR_PERIOD, 60);
173
-   obs_data_set_default_int(data, AMF_H264_HEADER_INSERTION_SPACING, 0);
174
-   obs_data_set_default_int(data, AMF_H264_BPICTURE_PATTERN, VCEBPicturePattern_None);
175
-   obs_data_set_default_int(data, AMF_H264_BPICTURE_REFERENCE, 0);
176
+   obs_data_set_int(data, "last" vstr(AMF_H264_BFRAME_PATTERN), -1);
177
+   obs_data_set_default_int(data, AMF_H264_BFRAME_PATTERN, VCEBFramePattern_None);
178
+   obs_data_set_int(data, "last" vstr(AMF_H264_BFRAME_REFERENCE), -1);
179
+   obs_data_set_default_int(data, AMF_H264_BFRAME_REFERENCE, 0);
180
+   obs_data_set_default_int(data, AMF_H264_BFRAME_REFERENCEDELTAQP, 2);
181
+   obs_data_set_default_int(data, AMF_H264_BFRAME_DELTAQP, 4);
182
    obs_data_set_default_int(data, AMF_H264_DEBLOCKINGFILTER, 1);
183
-   obs_data_set_default_int(data, AMF_H264_SLICESPERFRAME, 0);
184
-   obs_data_set_default_int(data, AMF_H264_INTRAREFRESHNUMMBSPERSLOT, 0);
185
 
186
    // Miscellaneous Control Properties
187
    obs_data_set_default_int(data, AMF_H264_SCANTYPE, VCEScanType_Progressive);
188
    obs_data_set_default_int(data, AMF_H264_MOTIONESTIMATION, 3);
189
 
190
-   // System Properties
191
-   obs_data_set_default_string(data, AMF_H264_DEVICE, "");
192
-   obs_data_set_default_int(data, AMF_H264_USE_OPENCL, 0);
193
+   // Experimental Properties
194
+   obs_data_set_default_int(data, AMF_H264_MAXIMUMLTRFRAMES, 0);
195
+   obs_data_set_default_int(data, AMF_H264_CODINGTYPE, VCECodingType_Default);
196
+   obs_data_set_default_int(data, AMF_H264_HEADER_INSERTION_SPACING, 0);
197
+   obs_data_set_default_int(data, AMF_H264_SLICESPERFRAME, 1);
198
+   obs_data_set_default_int(data, AMF_H264_SLICEMODE, VCESliceMode_Horizontal);
199
+   obs_data_set_default_int(data, AMF_H264_MAXIMUMSLICESIZE, INT_MAX);
200
+   obs_data_set_default_int(data, AMF_H264_SLICECONTROLMODE, VCESliceControlMode_Off);
201
+   obs_data_set_default_int(data, AMF_H264_SLICECONTROLSIZE, 0);
202
+   obs_data_set_default_int(data, AMF_H264_INTRAREFRESH_NUMBEROFSTRIPES, 0);
203
+   obs_data_set_default_int(data, AMF_H264_INTRAREFRESH_MACROBLOCKSPERSLOT, 0);
204
+   obs_data_set_default_int(data, AMF_H264_WAITFORTASK, 0);
205
+   obs_data_set_default_int(data, AMF_H264_PREANALYSISPASS, 0);
206
+   obs_data_set_default_int(data, AMF_H264_VBAQ, 0);
207
+   obs_data_set_default_int(data, AMF_H264_GOPSIZE, 0);
208
+   obs_data_set_default_int(data, AMF_H264_GOPALIGNMENT, 1);
209
+   obs_data_set_default_int(data, AMF_H264_MAXIMUMREFERENCEFRAMES, 4);
210
 
211
+   // System Properties
212
+   obs_data_set_string(data, "last" vstr(AMF_H264_VIDEOAPI), "");
213
+   obs_data_set_default_string(data, AMF_H264_VIDEOAPI, "");
214
+   obs_data_set_int(data, "last" vstr(AMF_H264_VIDEOADAPTER), 0);
215
+   obs_data_set_default_int(data, AMF_H264_VIDEOADAPTER, 0);
216
+   obs_data_set_default_int(data, AMF_H264_OPENCL, 0);
217
+   obs_data_set_int(data, "last" vstr(AMF_H264_VIEW), -1);
218
    obs_data_set_default_int(data, AMF_H264_VIEW, ViewMode::Basic);
219
-   obs_data_set_default_bool(data, AMF_H264_UNLOCK_PROPERTIES, false);
220
    obs_data_set_default_bool(data, AMF_H264_DEBUG, false);
221
 }
222
 
223
-static void fill_device_list(obs_property_t* p) {
224
-   std::vector<Plugin::API::Device> devices = Plugin::API::APIBase::EnumerateDevices();
225
+static void fill_api_list(obs_property_t* p) {
226
+   obs_property_list_clear(p);
227
+   for (auto api : Plugin::API::Base::EnumerateAPIs()) {
228
+       obs_property_list_add_string(p, api->GetName().c_str(), api->GetName().c_str());
229
+   }
230
+}
231
 
232
+static void fill_device_list(obs_property_t* p, const char* apiname) {
233
    obs_property_list_clear(p);
234
-   obs_property_list_add_string(p, TEXT_T(AMF_UTIL_DEFAULT), "");
235
-   for (Plugin::API::Device device : devices) {
236
-       obs_property_list_add_string(p, device.Name.c_str(), device.UniqueId.c_str());
237
+   auto api = Plugin::API::Base::GetAPIByName(std::string(apiname));
238
+   for (auto adapter : api->EnumerateAdapters()) {
239
+       obs_property_list_add_int(p, adapter.Name.c_str(), ((int64_t)adapter.idHigh << 32) + (int64_t)adapter.idLow);
240
    }
241
 }
242
 
243
@@ -259,8 +279,10 @@
244
    obs_property_list_add_int(p, TEXT_T(AMF_H264_USAGE_TRANSCODING), VCEUsage_Transcoding);
245
    obs_property_list_add_int(p, TEXT_T(AMF_H264_USAGE_ULTRALOWLATENCY), VCEUsage_UltraLowLatency);
246
    obs_property_list_add_int(p, TEXT_T(AMF_H264_USAGE_LOWLATENCY), VCEUsage_LowLatency);
247
-   //obs_property_list_add_int(list, TEXT_T(AMF_H264_USAGE_WEBCAM), VCEUsage_Webcam); // Requires SVC? SVC is not implemented by default.
248
+   // Webcam requires SVC, which is not something OBSs properties API makes easy to support. Nor would it look like anything usable.
249
+   //obs_property_list_add_int(list, TEXT_T(AMF_H264_USAGE_WEBCAM), VCEUsage_Webcam);
250
    #pragma endregion Usage
251
+
252
    #pragma region Quality Preset
253
    p = obs_properties_add_list(props, AMF_H264_QUALITY_PRESET, TEXT_T(AMF_H264_QUALITY_PRESET), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
254
    obs_property_set_long_description(p, TEXT_T(AMF_H264_QUALITY_PRESET_DESCRIPTION));
255
@@ -268,32 +290,19 @@
256
    obs_property_list_add_int(p, TEXT_T(AMF_H264_QUALITY_PRESET_BALANCED), VCEQualityPreset_Balanced);
257
    obs_property_list_add_int(p, TEXT_T(AMF_H264_QUALITY_PRESET_QUALITY), VCEQualityPreset_Quality);
258
    #pragma endregion Quality Preset
259
+
260
    #pragma region Profile
261
    p = obs_properties_add_list(props, AMF_H264_PROFILE, TEXT_T(AMF_H264_PROFILE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
262
    obs_property_set_long_description(p, TEXT_T(AMF_H264_PROFILE_DESCRIPTION));
263
-   obs_property_list_add_int(p, "NOT INITIALIZED", 0xFFFFFFFFFFFFFFFFull);
264
    #pragma endregion Profile
265
+
266
    #pragma region Profile Level
267
    p = obs_properties_add_list(props, AMF_H264_PROFILELEVEL, TEXT_T(AMF_H264_PROFILELEVEL), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
268
    obs_property_set_long_description(p, TEXT_T(AMF_H264_PROFILELEVEL_DESCRIPTION));
269
-   obs_property_list_add_int(p, "NOT INITIALIZED", 0xFFFFFFFFFFFFFFFFull);
270
    #pragma endregion Profile Levels
271
-   #pragma region Long Term Reference Frames
272
-   p = obs_properties_add_int_slider(props, AMF_H264_MAXIMUMLTRFRAMES, TEXT_T(AMF_H264_MAXIMUMLTRFRAMES), 0, 2, 1);
273
-   obs_property_set_long_description(p, TEXT_T(AMF_H264_MAXIMUMLTRFRAMES_DESCRIPTION));
274
-   obs_property_set_modified_callback(p, properties_modified);
275
-   #pragma endregion Long Term Reference Frames
276
-   #pragma region Coding Type
277
-   p = obs_properties_add_list(props, AMF_H264_CODINGTYPE, TEXT_T(AMF_H264_CODINGTYPE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
278
-   obs_property_set_long_description(p, TEXT_T(AMF_H264_CODINGTYPE_DESCRIPTION));
279
-   obs_property_list_add_int(p, TEXT_T(AMF_UTIL_DEFAULT), VCECodingType_Default);
280
-   obs_property_list_add_int(p, "CALVC", VCECodingType_CALV);
281
-   obs_property_list_add_int(p, "CABAC", VCECodingType_CABAC);
282
-   #pragma endregion Coding Type
283
    #pragma endregion Static Properties
284
 
285
    #pragma region Rate Control Properties
286
-   //p = obs_properties_add_bool(props, "rcp_delimiter", "------ Rate Control Properties ------");
287
    #pragma region Method
288
    p = obs_properties_add_list(props, AMF_H264_RATECONTROLMETHOD, TEXT_T(AMF_H264_RATECONTROLMETHOD), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
289
    obs_property_set_long_description(p, TEXT_T(AMF_H264_RATECONTROLMETHOD_DESCRIPTION));
290
@@ -303,6 +312,7 @@
291
    obs_property_list_add_int(p, TEXT_T(AMF_H264_RATECONTROLMETHOD_VBR_LAT), VCERateControlMethod_VariableBitrate_LatencyConstrained);
292
    obs_property_set_modified_callback(p, properties_modified);
293
    #pragma endregion Method
294
+
295
    #pragma region Method Parameters
296
    /// Bitrate Constraints
297
    p = obs_properties_add_int(props, AMF_H264_BITRATE_TARGET, TEXT_T(AMF_H264_BITRATE_TARGET), 0,
298
@@ -311,11 +321,13 @@
299
    p = obs_properties_add_int(props, AMF_H264_BITRATE_PEAK, TEXT_T(AMF_H264_BITRATE_PEAK), 0,
300
        1, 1);
301
    obs_property_set_long_description(p, TEXT_T(AMF_H264_BITRATE_PEAK_DESCRIPTION));
302
+
303
    /// Minimum QP, Maximum QP
304
    p = obs_properties_add_int_slider(props, AMF_H264_QP_MINIMUM, TEXT_T(AMF_H264_QP_MINIMUM), 0, 51, 1);
305
    obs_property_set_long_description(p, TEXT_T(AMF_H264_QP_MINIMUM_DESCRIPTION));
306
    p = obs_properties_add_int_slider(props, AMF_H264_QP_MAXIMUM, TEXT_T(AMF_H264_QP_MAXIMUM), 0, 51, 1);
307
    obs_property_set_long_description(p, TEXT_T(AMF_H264_QP_MAXIMUM_DESCRIPTION));
308
+
309
    /// Method: Constant QP
310
    p = obs_properties_add_int_slider(props, AMF_H264_QP_IFRAME, TEXT_T(AMF_H264_QP_IFRAME), 0, 51, 1);
311
    obs_property_set_long_description(p, TEXT_T(AMF_H264_QP_IFRAME_DESCRIPTION));
312
@@ -324,6 +336,7 @@
313
    p = obs_properties_add_int_slider(props, AMF_H264_QP_BFRAME, TEXT_T(AMF_H264_QP_BFRAME), 0, 51, 1);
314
    obs_property_set_long_description(p, TEXT_T(AMF_H264_QP_BFRAME_DESCRIPTION));
315
    #pragma endregion Method Parameters
316
+
317
    #pragma region VBV Buffer
318
    p = obs_properties_add_list(props, AMF_H264_VBVBUFFER, TEXT_T(AMF_H264_VBVBUFFER), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
319
    obs_property_set_long_description(p, TEXT_T(AMF_H264_VBVBUFFER_DESCRIPTION));
320
@@ -337,20 +350,24 @@
321
    p = obs_properties_add_float_slider(props, AMF_H264_VBVBUFFER_FULLNESS, TEXT_T(AMF_H264_VBVBUFFER_FULLNESS), 0.0, 100.0, 100.0 / 64.0);
322
    obs_property_set_long_description(p, TEXT_T(AMF_H264_VBVBUFFER_FULLNESS_DESCRIPTION));
323
    #pragma endregion VBV Buffer
324
+
325
    /// Max Access Unit Size
326
    p = obs_properties_add_int_slider(props, AMF_H264_MAXIMUMACCESSUNITSIZE, TEXT_T(AMF_H264_MAXIMUMACCESSUNITSIZE), 0, 100000000, 1);
327
    obs_property_set_long_description(p, TEXT_T(AMF_H264_MAXIMUMACCESSUNITSIZE_DESCRIPTION));
328
+
329
    #pragma region Flags
330
    /// Filler Data (Only supported by CBR so far)
331
    p = obs_properties_add_list(props, AMF_H264_FILLERDATA, TEXT_T(AMF_H264_FILLERDATA), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
332
    obs_property_set_long_description(p, TEXT_T(AMF_H264_FILLERDATA_DESCRIPTION));
333
    obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_DISABLED), 0);
334
    obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_ENABLED), 1);
335
+
336
    /// Frame Skipping
337
    p = obs_properties_add_list(props, AMF_H264_FRAMESKIPPING, TEXT_T(AMF_H264_FRAMESKIPPING), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
338
    obs_property_set_long_description(p, TEXT_T(AMF_H264_FRAMESKIPPING_DESCRIPTION));
339
    obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_DISABLED), 0);
340
    obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_ENABLED), 1);
341
+
342
    /// Enforce Hypothetical Reference Decoder Compatibility
343
    p = obs_properties_add_list(props, AMF_H264_ENFORCEHRDCOMPATIBILITY, TEXT_T(AMF_H264_ENFORCEHRDCOMPATIBILITY), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
344
    obs_property_set_long_description(p, TEXT_T(AMF_H264_ENFORCEHRDCOMPATIBILITY_DESCRIPTION));
345
@@ -359,53 +376,47 @@
346
    #pragma endregion Flags
347
    #pragma endregion Rate Control Properties
348
 
349
-   #pragma region Picture Control Properties
350
-   //p = obs_properties_add_bool(props, "pcp_delimiter", "------ Picture Control Properties ------");
351
-   #pragma region IDR Period / Keyframe Interval / Header Insertion Spacing
352
+   #pragma region Frame Control Properties
353
+   #pragma region IDR Period / Keyframe Interval
354
    p = obs_properties_add_float(props, AMF_H264_KEYFRAME_INTERVAL, TEXT_T(AMF_H264_KEYFRAME_INTERVAL), 0, 100, 0.001);
355
    obs_property_set_long_description(p, TEXT_T(AMF_H264_KEYFRAME_INTERVAL_DESCRIPTION));
356
    p = obs_properties_add_int(props, AMF_H264_IDR_PERIOD, TEXT_T(AMF_H264_IDR_PERIOD), 1, 1000, 1);
357
    obs_property_set_long_description(p, TEXT_T(AMF_H264_IDR_PERIOD_DESCRIPTION));
358
-   p = obs_properties_add_int(props, AMF_H264_HEADER_INSERTION_SPACING, TEXT_T(AMF_H264_HEADER_INSERTION_SPACING), 0, 1000, 1);
359
-   obs_property_set_long_description(p, TEXT_T(AMF_H264_HEADER_INSERTION_SPACING_DESCRIPTION));
360
-   #pragma endregion IDR Period / Keyframe Interval / Header Insertion Spacing
361
-   #pragma region B-Pictures
362
-   /// B-Pictures Pattern
363
-   p = obs_properties_add_int_slider(props, AMF_H264_BPICTURE_PATTERN, TEXT_T(AMF_H264_BPICTURE_PATTERN),
364
-       VCEBPicturePattern_None, VCEBPicturePattern_Three, 1);
365
-   obs_property_set_long_description(p, TEXT_T(AMF_H264_BPICTURE_PATTERN_DESCRIPTION));
366
+   #pragma endregion IDR Period / Keyframe Interval
367
+
368
+   #pragma region B-Frames
369
+   /// B-Frames Pattern
370
+   p = obs_properties_add_int_slider(props, AMF_H264_BFRAME_PATTERN, TEXT_T(AMF_H264_BFRAME_PATTERN),
371
+       VCEBFramePattern_None, VCEBFramePattern_Three, 1);
372
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_BFRAME_PATTERN_DESCRIPTION));
373
    obs_property_set_modified_callback(p, properties_modified);
374
    /// Enable Reference to B-Frames (2nd Generation GCN and newer)
375
-   p = obs_properties_add_list(props, AMF_H264_BPICTURE_REFERENCE, TEXT_T(AMF_H264_BPICTURE_REFERENCE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
376
-   obs_property_set_long_description(p, TEXT_T(AMF_H264_BPICTURE_REFERENCE_DESCRIPTION));
377
+   p = obs_properties_add_list(props, AMF_H264_BFRAME_REFERENCE, TEXT_T(AMF_H264_BFRAME_REFERENCE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
378
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_BFRAME_REFERENCE_DESCRIPTION));
379
    obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_DISABLED), 0);
380
    obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_ENABLED), 1);
381
    obs_property_set_modified_callback(p, properties_modified);
382
-   /// B-Picture Delta QP
383
-   p = obs_properties_add_int_slider(props, AMF_H264_QP_BPICTURE_DELTA, TEXT_T(AMF_H264_QP_BPICTURE_DELTA), -10, 10, 1);
384
-   obs_property_set_long_description(p, TEXT_T(AMF_H264_QP_BPICTURE_DELTA_DESCRIPTION));
385
-   p = obs_properties_add_int_slider(props, AMF_H264_QP_REFERENCE_BPICTURE_DELTA, TEXT_T(AMF_H264_QP_REFERENCE_BPICTURE_DELTA), -10, 10, 1);
386
-   obs_property_set_long_description(p, TEXT_T(AMF_H264_QP_REFERENCE_BPICTURE_DELTA_DESCRIPTION));
387
-   #pragma endregion B-Pictures
388
+   /// B-Frame Delta QP
389
+   p = obs_properties_add_int_slider(props, AMF_H264_BFRAME_REFERENCEDELTAQP, TEXT_T(AMF_H264_BFRAME_REFERENCEDELTAQP), -10, 10, 1);
390
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_BFRAME_REFERENCEDELTAQP_DESCRIPTION));
391
+   p = obs_properties_add_int_slider(props, AMF_H264_BFRAME_DELTAQP, TEXT_T(AMF_H264_BFRAME_DELTAQP), -10, 10, 1);
392
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_BFRAME_DELTAQP_DESCRIPTION));
393
+   #pragma endregion B-Frames
394
+
395
    /// De-Blocking Filter
396
    p = obs_properties_add_list(props, AMF_H264_DEBLOCKINGFILTER, TEXT_T(AMF_H264_DEBLOCKINGFILTER), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
397
    obs_property_set_long_description(p, TEXT_T(AMF_H264_DEBLOCKINGFILTER_DESCRIPTION));
398
    obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_DISABLED), 0);
399
    obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_ENABLED), 1);
400
-   /// Number of Slices Per Frame 
401
-   p = obs_properties_add_int_slider(props, AMF_H264_SLICESPERFRAME, TEXT_T(AMF_H264_SLICESPERFRAME), 0, 8160, 1);
402
-   obs_property_set_long_description(p, TEXT_T(AMF_H264_SLICESPERFRAME_DESCRIPTION));
403
-   /// Intra Refresh Number of Macro Blocks per Slot
404
-   obs_properties_add_int_slider(props, AMF_H264_INTRAREFRESHNUMMBSPERSLOT, TEXT_T(AMF_H264_INTRAREFRESHNUMMBSPERSLOT), 0, 8160, 1);
405
-   #pragma endregion Picture Control Properties
406
+   #pragma endregion Frame Control Properties
407
 
408
    #pragma region Miscellaneous Control Properties
409
-   //p = obs_properties_add_bool(props, "msc_delimiter", "------ Miscellaneous Properties ------");
410
    /// Scan Type
411
    p = obs_properties_add_list(props, AMF_H264_SCANTYPE, TEXT_T(AMF_H264_SCANTYPE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
412
    obs_property_set_long_description(p, TEXT_T(AMF_H264_SCANTYPE_DESCRIPTION));
413
    obs_property_list_add_int(p, TEXT_T(AMF_H264_SCANTYPE_PROGRESSIVE), VCEScanType_Progressive);
414
    obs_property_list_add_int(p, TEXT_T(AMF_H264_SCANTYPE_INTERLACED), VCEScanType_Interlaced);
415
+
416
    /// Motion Estimation
417
    p = obs_properties_add_list(props, AMF_H264_MOTIONESTIMATION, TEXT_T(AMF_H264_MOTIONESTIMATION), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
418
    obs_property_set_long_description(p, TEXT_T(AMF_H264_MOTIONESTIMATION_DESCRIPTION));
419
@@ -415,18 +426,111 @@
420
    obs_property_list_add_int(p, TEXT_T(AMF_H264_MOTIONESTIMATION_BOTH), 3);
421
    #pragma endregion Miscellaneous Control Properties
422
 
423
+   #pragma region Experimental Properties
424
+   #pragma region Coding Type
425
+   p = obs_properties_add_list(props, AMF_H264_CODINGTYPE, TEXT_T(AMF_H264_CODINGTYPE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
426
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_CODINGTYPE_DESCRIPTION));
427
+   obs_property_list_add_int(p, TEXT_T(AMF_UTIL_DEFAULT), VCECodingType_Default);
428
+   obs_property_list_add_int(p, "CABAC", VCECodingType_CABAC);
429
+   obs_property_list_add_int(p, "CALVC", VCECodingType_CALVC);
430
+   #pragma endregion Coding Type
431
+
432
+   #pragma region Long Term Reference Frames
433
+   p = obs_properties_add_int_slider(props, AMF_H264_MAXIMUMLTRFRAMES, TEXT_T(AMF_H264_MAXIMUMLTRFRAMES), 0, 2, 1);
434
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_MAXIMUMLTRFRAMES_DESCRIPTION));
435
+   obs_property_set_modified_callback(p, properties_modified);
436
+   #pragma endregion Long Term Reference Frames
437
+
438
+   /// Header Insertion Spacing
439
+   p = obs_properties_add_int(props, AMF_H264_HEADER_INSERTION_SPACING, TEXT_T(AMF_H264_HEADER_INSERTION_SPACING), 0, 1000, 1);
440
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_HEADER_INSERTION_SPACING_DESCRIPTION));
441
+
442
+   #pragma region Slicing
443
+   /// Number of Slices Per Frame 
444
+   p = obs_properties_add_int_slider(props, AMF_H264_SLICESPERFRAME, TEXT_T(AMF_H264_SLICESPERFRAME), 1, 8160, 1);
445
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_SLICESPERFRAME_DESCRIPTION));
446
+
447
+   /// Slice Mode
448
+   p = obs_properties_add_list(props, AMF_H264_SLICEMODE, TEXT_T(AMF_H264_SLICEMODE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
449
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_SLICEMODE_DESCRIPTION));
450
+   obs_property_list_add_int(p, "Horizontal", VCESliceMode_Horizontal);
451
+   obs_property_list_add_int(p, "Vertical", VCESliceMode_Vertical);
452
+
453
+   /// Maximum Slice Size
454
+   p = obs_properties_add_int_slider(props, AMF_H264_MAXIMUMSLICESIZE, TEXT_T(AMF_H264_MAXIMUMSLICESIZE), 1, INT_MAX, 1);
455
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_MAXIMUMSLICESIZE_DESCRIPTION));
456
+
457
+   /// Slice Control Mode
458
+   p = obs_properties_add_list(props, AMF_H264_SLICECONTROLMODE, TEXT_T(AMF_H264_SLICECONTROLMODE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
459
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_SLICECONTROLMODE_DESCRIPTION));
460
+   obs_property_list_add_int(p, Utility::SliceControlModeAsString(VCESliceControlMode_Off), VCESliceControlMode_Off);
461
+   obs_property_list_add_int(p, Utility::SliceControlModeAsString(VCESliceControlMode_Macroblock), VCESliceControlMode_Macroblock);
462
+   obs_property_list_add_int(p, Utility::SliceControlModeAsString(VCESliceControlMode_Macroblock_Row), VCESliceControlMode_Macroblock_Row);
463
+
464
+   /// Slice Control Size
465
+   p = obs_properties_add_int_slider(props, AMF_H264_SLICECONTROLSIZE, TEXT_T(AMF_H264_SLICECONTROLSIZE), 0, 34560, 1); // 4096x2160 / 16x16
466
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_SLICECONTROLSIZE_DESCRIPTION));
467
+   #pragma endregion Slicing
468
+
469
+   #pragma region Intra Refresh
470
+   /// Intra Refresh: Number of Stripes
471
+   p = obs_properties_add_int_slider(props, AMF_H264_INTRAREFRESH_NUMBEROFSTRIPES, TEXT_T(AMF_H264_INTRAREFRESH_NUMBEROFSTRIPES), 0, INT_MAX, 1);
472
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_INTRAREFRESH_NUMBEROFSTRIPES_DESCRIPTION));
473
+
474
+   /// Intra Refresh: Macroblocks Per Slot
475
+   p = obs_properties_add_int_slider(props, AMF_H264_INTRAREFRESH_MACROBLOCKSPERSLOT, TEXT_T(AMF_H264_INTRAREFRESH_MACROBLOCKSPERSLOT), 0, 34560, 1); // 4096x2160 / 16x16
476
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_INTRAREFRESH_MACROBLOCKSPERSLOT_DESCRIPTION));
477
+   #pragma endregion Intra Refresh
478
+
479
+   /// Wait For Task
480
+   p = obs_properties_add_list(props, AMF_H264_WAITFORTASK, TEXT_T(AMF_H264_WAITFORTASK), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
481
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_WAITFORTASK_DESCRIPTION));
482
+   obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_DISABLED), 0);
483
+   obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_ENABLED), 1);
484
+
485
+   /// Preanalysis Pass
486
+   p = obs_properties_add_list(props, AMF_H264_PREANALYSISPASS, TEXT_T(AMF_H264_PREANALYSISPASS), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
487
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_PREANALYSISPASS_DESCRIPTION));
488
+   obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_DISABLED), 0);
489
+   obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_ENABLED), 1);
490
+
491
+   /// VBAQ
492
+   p = obs_properties_add_list(props, AMF_H264_VBAQ, TEXT_T(AMF_H264_VBAQ), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
493
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_VBAQ_DESCRIPTION));
494
+   obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_DISABLED), 0);
495
+   obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_ENABLED), 1);
496
+
497
+   /// GOP Size
498
+   p = obs_properties_add_int(props, AMF_H264_GOPSIZE, TEXT_T(AMF_H264_GOPSIZE), 0, INT_MAX, 1);
499
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_GOPSIZE_DESCRIPTION));
500
+
501
+   /// GOP Alignment
502
+   p = obs_properties_add_list(props, AMF_H264_GOPALIGNMENT, TEXT_T(AMF_H264_GOPALIGNMENT), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
503
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_GOPALIGNMENT_DESCRIPTION));
504
+   obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_DISABLED), 0);
505
+   obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_ENABLED), 1);
506
+
507
+   /// GOP Size
508
+   p = obs_properties_add_int_slider(props, AMF_H264_MAXIMUMREFERENCEFRAMES, TEXT_T(AMF_H264_MAXIMUMREFERENCEFRAMES), 1, 1, 1);
509
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_MAXIMUMREFERENCEFRAMES_DESCRIPTION));
510
+
511
+   #pragma endregion Experimental Properties
512
+
513
    #pragma region System Properties
514
-   //p = obs_properties_add_bool(props, "sys_delimiter", "------ System Properties ------");
515
-   #pragma region Device Selection
516
-   p = obs_properties_add_list(props, AMF_H264_DEVICE, TEXT_T(AMF_H264_DEVICE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
517
-   fill_device_list(p);
518
-   obs_property_set_long_description(p, TEXT_T(AMF_H264_DEVICE_DESCRIPTION));
519
+   /// Video API
520
+   p = obs_properties_add_list(props, AMF_H264_VIDEOAPI, TEXT_T(AMF_H264_VIDEOAPI), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
521
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_VIDEOAPI_DESCRIPTION));
522
+   obs_property_set_modified_callback(p, properties_modified);
523
+   fill_api_list(p);
524
+
525
+   /// Video Adapter
526
+   p = obs_properties_add_list(props, AMF_H264_VIDEOADAPTER, TEXT_T(AMF_H264_VIDEOADAPTER), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
527
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_VIDEOADAPTER_DESCRIPTION));
528
    obs_property_set_modified_callback(p, properties_modified);
529
-   #pragma endregion Device Selection
530
 
531
-   /// Compute Type
532
-   p = obs_properties_add_list(props, AMF_H264_USE_OPENCL, TEXT_T(AMF_H264_USE_OPENCL), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
533
-   obs_property_set_long_description(p, TEXT_T(AMF_H264_USE_OPENCL_DESCRIPTION));
534
+   /// OpenCL
535
+   p = obs_properties_add_list(props, AMF_H264_OPENCL, TEXT_T(AMF_H264_OPENCL), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
536
+   obs_property_set_long_description(p, TEXT_T(AMF_H264_OPENCL_DESCRIPTION));
537
    obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_DISABLED), 0);
538
    obs_property_list_add_int(p, TEXT_T(AMF_UTIL_TOGGLE_ENABLED), 1);
539
 
540
@@ -438,10 +542,6 @@
541
    obs_property_list_add_int(p, TEXT_T(AMF_H264_VIEW_EXPERT), ViewMode::Expert);
542
    obs_property_list_add_int(p, TEXT_T(AMF_H264_VIEW_MASTER), ViewMode::Master);
543
    obs_property_set_modified_callback(p, properties_modified);
544
-   /// Unlock Properties to full range.
545
-   p = obs_properties_add_bool(props, AMF_H264_UNLOCK_PROPERTIES, TEXT_T(AMF_H264_UNLOCK_PROPERTIES));
546
-   obs_property_set_long_description(p, TEXT_T(AMF_H264_UNLOCK_PROPERTIES_DESCRIPTION));
547
-   obs_property_set_modified_callback(p, properties_modified);
548
 
549
    /// Debug
550
    p = obs_properties_add_bool(props, AMF_H264_DEBUG, TEXT_T(AMF_H264_DEBUG));
551
@@ -499,20 +599,18 @@
552
    obs_property_t* p;
553
 
554
    #pragma region Presets
555
-   Presets preset = (Presets)obs_data_get_int(data, AMF_H264_PRESET);
556
-   { // Reset State
557
+   Presets lastPreset = (Presets)obs_data_get_int(data, "last" vstr(AMF_H264_PRESET)),
558
+       preset = (Presets)obs_data_get_int(data, AMF_H264_PRESET);
559
+   if (lastPreset != preset) { // Reset State
560
        obs_property_t* pn = obs_properties_first(props);
561
        do {
562
            obs_property_set_enabled(pn, true);
563
        } while (obs_property_next(&pn));
564
 
565
-       if (preset != Presets::None) {
566
-           // System Properties
567
-           obs_data_set_bool(data, AMF_H264_UNLOCK_PROPERTIES, false);
568
-           obs_property_set_enabled(obs_properties_get(props, AMF_H264_UNLOCK_PROPERTIES), false);
569
-           result = true;
570
-       }
571
+       result = true;
572
    }
573
+   if (preset != Presets::None)
574
+       result = true;
575
 
576
    switch (preset) {
577
        case ResetToDefaults:
578
@@ -521,6 +619,11 @@
579
            obs_property_t* pn = obs_properties_first(props);
580
            do {
581
                const char* name = obs_property_name(pn);
582
+
583
+               // Do not reset Video Adapter or API.
584
+               if ((strcmp(name, AMF_H264_VIDEOAPI) == 0) || (strcmp(name, AMF_H264_VIDEOADAPTER) == 0))
585
+                   continue;
586
+
587
                switch (obs_property_get_type(pn)) {
588
                    case obs_property_type::OBS_PROPERTY_BOOL:
589
                        obs_data_set_bool(data, name, obs_data_get_default_bool(data, name));
590
@@ -577,10 +680,10 @@
591
            /*obs_data_set_int(data, AMF_H264_QP_IFRAME, 0);
592
            obs_data_set_int(data, AMF_H264_QP_PFRAME, 0);
593
            obs_data_set_int(data, AMF_H264_QP_BFRAME, 0);*/
594
-           obs_data_set_int(data, AMF_H264_QP_BPICTURE_DELTA, 0);
595
-           obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_BPICTURE_DELTA), false);
596
-           obs_data_set_int(data, AMF_H264_QP_REFERENCE_BPICTURE_DELTA, 0);
597
-           obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_REFERENCE_BPICTURE_DELTA), false);
598
+           obs_data_set_int(data, AMF_H264_BFRAME_DELTAQP, 0);
599
+           obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_DELTAQP), false);
600
+           obs_data_set_int(data, AMF_H264_BFRAME_REFERENCEDELTAQP, 0);
601
+           obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_REFERENCEDELTAQP), false);
602
            //obs_data_set_int(data, AMF_H264_VBVBUFFER, 0);
603
            //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER), false);
604
            //obs_data_set_double(data, AMF_H264_VBVBUFFER_STRICTNESS, 0);
605
@@ -593,13 +696,13 @@
606
            //obs_data_set_int(data, AMF_H264_FRAMESKIPPING, 0);
607
            //obs_data_set_int(data, AMF_H264_ENFORCEHRDCOMPATIBILITY, 0);
608
 
609
-           // Picture Control Properties
610
+           // Frame Control Properties
611
            obs_data_set_double(data, AMF_H264_KEYFRAME_INTERVAL, 1);
612
            obs_property_set_enabled(obs_properties_get(props, AMF_H264_KEYFRAME_INTERVAL), false);
613
            //obs_data_set_int(data, AMF_H264_IDR_PERIOD, 60);
614
            //obs_data_set_int(data, AMF_H264_HEADER_INSERTION_SPACING, 0);
615
-           //obs_data_set_int(data, AMF_H264_BPICTURE_PATTERN, obs_data_get_default_int(data, AMF_H264_BPICTURE_PATTERN));
616
-           //obs_data_set_int(data, AMF_H264_BPICTURE_REFERENCE, obs_data_get_default_int(data, AMF_H264_BPICTURE_REFERENCE));
617
+           //obs_data_set_int(data, AMF_H264_BFrame_PATTERN, obs_data_get_default_int(data, AMF_H264_BFrame_PATTERN));
618
+           //obs_data_set_int(data, AMF_H264_BFrame_REFERENCE, obs_data_get_default_int(data, AMF_H264_BFrame_REFERENCE));
619
            //obs_data_set_int(data, AMF_H264_SLICESPERFRAME, 0);
620
            //obs_data_set_int(data, AMF_H264_INTRAREFRESHNUMMBSPERSLOT, 0);
621
 
622
@@ -635,10 +738,10 @@
623
            obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_PFRAME), false);
624
            obs_data_set_int(data, AMF_H264_QP_BFRAME, 22);
625
            obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_BFRAME), false);
626
-           obs_data_set_int(data, AMF_H264_QP_BPICTURE_DELTA, -2);
627
-           obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_BPICTURE_DELTA), false);
628
-           obs_data_set_int(data, AMF_H264_QP_REFERENCE_BPICTURE_DELTA, -2);
629
-           obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_REFERENCE_BPICTURE_DELTA), false);
630
+           obs_data_set_int(data, AMF_H264_BFRAME_DELTAQP, -2);
631
+           obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_DELTAQP), false);
632
+           obs_data_set_int(data, AMF_H264_BFRAME_REFERENCEDELTAQP, -2);
633
+           obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_REFERENCEDELTAQP), false);
634
            //obs_data_set_int(data, AMF_H264_VBVBUFFER, 0);
635
            //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER), false);
636
            //obs_data_set_double(data, AMF_H264_VBVBUFFER_STRICTNESS, 0);
637
@@ -650,13 +753,13 @@
638
            //obs_data_set_int(data, AMF_H264_FRAMESKIPPING, 0);
639
            //obs_data_set_int(data, AMF_H264_ENFORCEHRDCOMPATIBILITY, 0);
640
 
641
-           // Picture Control Properties
642
+           // Frame Control Properties
643
            obs_data_set_double(data, AMF_H264_KEYFRAME_INTERVAL, 1);
644
            obs_property_set_enabled(obs_properties_get(props, AMF_H264_KEYFRAME_INTERVAL), false);
645
            //obs_data_set_int(data, AMF_H264_IDR_PERIOD, 60);
646
            //obs_data_set_int(data, AMF_H264_HEADER_INSERTION_SPACING, 0);
647
-           //obs_data_set_int(data, AMF_H264_BPICTURE_PATTERN, obs_data_get_default_int(data, AMF_H264_BPICTURE_PATTERN));
648
-           //obs_data_set_int(data, AMF_H264_BPICTURE_REFERENCE, obs_data_get_default_int(data, AMF_H264_BPICTURE_REFERENCE));
649
+           //obs_data_set_int(data, AMF_H264_BFrame_PATTERN, obs_data_get_default_int(data, AMF_H264_BFrame_PATTERN));
650
+           //obs_data_set_int(data, AMF_H264_BFrame_REFERENCE, obs_data_get_default_int(data, AMF_H264_BFrame_REFERENCE));
651
            //obs_data_set_int(data, AMF_H264_SLICESPERFRAME, 0);
652
            //obs_data_set_int(data, AMF_H264_INTRAREFRESHNUMMBSPERSLOT, 0);
653
 
654
@@ -692,10 +795,10 @@
655
            obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_PFRAME), false);
656
            obs_data_set_int(data, AMF_H264_QP_BFRAME, 17);
657
            obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_BFRAME), false);
658
-           obs_data_set_int(data, AMF_H264_QP_BPICTURE_DELTA, -2);
659
-           obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_BPICTURE_DELTA), false);
660
-           obs_data_set_int(data, AMF_H264_QP_REFERENCE_BPICTURE_DELTA, -2);
661
-           obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_REFERENCE_BPICTURE_DELTA), false);
662
+           obs_data_set_int(data, AMF_H264_BFRAME_DELTAQP, -2);
663
+           obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_DELTAQP), false);
664
+           obs_data_set_int(data, AMF_H264_BFRAME_REFERENCEDELTAQP, -2);
665
+           obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_REFERENCEDELTAQP), false);
666
            //obs_data_set_int(data, AMF_H264_VBVBUFFER, 0);
667
            //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER), false);
668
            //obs_data_set_double(data, AMF_H264_VBVBUFFER_STRICTNESS, 0);
669
@@ -707,13 +810,13 @@
670
            //obs_data_set_int(data, AMF_H264_FRAMESKIPPING, 0);
671
            //obs_data_set_int(data, AMF_H264_ENFORCEHRDCOMPATIBILITY, 0);
672
 
673
-           // Picture Control Properties
674
+           // Frame Control Properties
675
            obs_data_set_double(data, AMF_H264_KEYFRAME_INTERVAL, 1);
676
            obs_property_set_enabled(obs_properties_get(props, AMF_H264_KEYFRAME_INTERVAL), false);
677
            //obs_data_set_int(data, AMF_H264_IDR_PERIOD, 60);
678
            //obs_data_set_int(data, AMF_H264_HEADER_INSERTION_SPACING, 0);
679
-           //obs_data_set_int(data, AMF_H264_BPICTURE_PATTERN, obs_data_get_default_int(data, AMF_H264_BPICTURE_PATTERN));
680
-           //obs_data_set_int(data, AMF_H264_BPICTURE_REFERENCE, obs_data_get_default_int(data, AMF_H264_BPICTURE_REFERENCE));
681
+           //obs_data_set_int(data, AMF_H264_BFRAME_PATTERN, obs_data_get_default_int(data, AMF_H264_BFRAME_PATTERN));
682
+           //obs_data_set_int(data, AMF_H264_BFRAME_REFERENCE, obs_data_get_default_int(data, AMF_H264_BFRAME_REFERENCE));
683
            //obs_data_set_int(data, AMF_H264_SLICESPERFRAME, 0);
684
            //obs_data_set_int(data, AMF_H264_INTRAREFRESHNUMMBSPERSLOT, 0);
685
 
686
@@ -749,10 +852,10 @@
687
            obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_PFRAME), false);
688
            obs_data_set_int(data, AMF_H264_QP_BFRAME, 0);
689
            obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_BFRAME), false);
690
-           obs_data_set_int(data, AMF_H264_QP_BPICTURE_DELTA, 0);
691
-           obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_BPICTURE_DELTA), false);
692
-           obs_data_set_int(data, AMF_H264_QP_REFERENCE_BPICTURE_DELTA, 0);
693
-           obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_REFERENCE_BPICTURE_DELTA), false);
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, 0);
701
@@ -764,16 +867,16 @@
702
            //obs_data_set_int(data, AMF_H264_FRAMESKIPPING, 0);
703
            //obs_data_set_int(data, AMF_H264_ENFORCEHRDCOMPATIBILITY, 0);
704
 
705
-           // Picture Control Properties
706
+           // Frame Control Properties
707
            obs_data_set_double(data, AMF_H264_KEYFRAME_INTERVAL, 1);
708
            obs_property_set_enabled(obs_properties_get(props, AMF_H264_KEYFRAME_INTERVAL), false);
709
            obs_data_set_int(data, AMF_H264_IDR_PERIOD, 30);
710
            obs_property_set_enabled(obs_properties_get(props, AMF_H264_IDR_PERIOD), false);
711
            //obs_data_set_int(data, AMF_H264_HEADER_INSERTION_SPACING, 0);
712
-           obs_data_set_int(data, AMF_H264_BPICTURE_PATTERN, 0);
713
-           obs_property_set_enabled(obs_properties_get(props, AMF_H264_BPICTURE_PATTERN), false);
714
-           obs_data_set_int(data, AMF_H264_BPICTURE_REFERENCE, 0);
715
-           obs_property_set_enabled(obs_properties_get(props, AMF_H264_BPICTURE_REFERENCE), false);
716
+           obs_data_set_int(data, AMF_H264_BFRAME_PATTERN, 0);
717
+           obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_PATTERN), false);
718
+           obs_data_set_int(data, AMF_H264_BFRAME_REFERENCE, 0);
719
+           obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_REFERENCE), false);
720
            //obs_data_set_int(data, AMF_H264_SLICESPERFRAME, 0);
721
            //obs_data_set_int(data, AMF_H264_INTRAREFRESHNUMMBSPERSLOT, 0);
722
 
723
@@ -813,10 +916,10 @@
724
            /*obs_data_set_int(data, AMF_H264_QP_IFRAME, 0);
725
            obs_data_set_int(data, AMF_H264_QP_PFRAME, 0);
726
            obs_data_set_int(data, AMF_H264_QP_BFRAME, 0);*/
727
-           obs_data_set_int(data, AMF_H264_QP_BPICTURE_DELTA, 0);
728
-           obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_BPICTURE_DELTA), false);
729
-           obs_data_set_int(data, AMF_H264_QP_REFERENCE_BPICTURE_DELTA, 0);
730
-           obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_REFERENCE_BPICTURE_DELTA), false);
731
+           obs_data_set_int(data, AMF_H264_BFRAME_DELTAQP, 0);
732
+           obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_DELTAQP), false);
733
+           obs_data_set_int(data, AMF_H264_BFRAME_REFERENCEDELTAQP, 0);
734
+           obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_REFERENCEDELTAQP), false);
735
            //obs_data_set_int(data, AMF_H264_VBVBUFFER, 0);
736
            //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER), false);
737
            //obs_data_set_double(data, AMF_H264_VBVBUFFER_STRICTNESS, 80);
738
@@ -829,13 +932,13 @@
739
            //obs_data_set_int(data, AMF_H264_FRAMESKIPPING, 0);
740
            //obs_data_set_int(data, AMF_H264_ENFORCEHRDCOMPATIBILITY, 0);
741
 
742
-           // Picture Control Properties
743
+           // Frame Control Properties
744
            obs_data_set_double(data, AMF_H264_KEYFRAME_INTERVAL, 2);
745
            obs_property_set_enabled(obs_properties_get(props, AMF_H264_KEYFRAME_INTERVAL), false);
746
            //obs_data_set_int(data, AMF_H264_IDR_PERIOD, 120);
747
            //obs_data_set_int(data, AMF_H264_HEADER_INSERTION_SPACING, 0);
748
-           //obs_data_set_int(data, AMF_H264_BPICTURE_PATTERN, 0);
749
-           //obs_data_set_int(data, AMF_H264_BPICTURE_REFERENCE, 0);
750
+           //obs_data_set_int(data, AMF_H264_BFRAME_PATTERN, 0);
751
+           //obs_data_set_int(data, AMF_H264_BFRAME_REFERENCE, 0);
752
            //obs_data_set_int(data, AMF_H264_SLICESPERFRAME, 0);
753
            //obs_data_set_int(data, AMF_H264_INTRAREFRESHNUMMBSPERSLOT, 0);
754
 
755
@@ -874,10 +977,10 @@
756
            /*obs_data_set_int(data, AMF_H264_QP_IFRAME, 0);
757
            obs_data_set_int(data, AMF_H264_QP_PFRAME, 0);
758
            obs_data_set_int(data, AMF_H264_QP_BFRAME, 0);*/
759
-           obs_data_set_int(data, AMF_H264_QP_BPICTURE_DELTA, 0);
760
-           obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_BPICTURE_DELTA), false);
761
-           obs_data_set_int(data, AMF_H264_QP_REFERENCE_BPICTURE_DELTA, 0);
762
-           obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_REFERENCE_BPICTURE_DELTA), false);
763
+           obs_data_set_int(data, AMF_H264_BFRAME_DELTAQP, 0);
764
+           obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_DELTAQP), false);
765
+           obs_data_set_int(data, AMF_H264_BFRAME_REFERENCEDELTAQP, 0);
766
+           obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_REFERENCEDELTAQP), false);
767
            //obs_data_set_int(data, AMF_H264_VBVBUFFER, 0);
768
            //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER), false);
769
            //obs_data_set_double(data, AMF_H264_VBVBUFFER_STRICTNESS, 80);
770
@@ -890,13 +993,13 @@
771
            //obs_data_set_int(data, AMF_H264_FRAMESKIPPING, 0);
772
            //obs_data_set_int(data, AMF_H264_ENFORCEHRDCOMPATIBILITY, 0);
773
 
774
-           // Picture Control Properties
775
+           // Frame Control Properties
776
            obs_data_set_double(data, AMF_H264_KEYFRAME_INTERVAL, 2);
777
            obs_property_set_enabled(obs_properties_get(props, AMF_H264_KEYFRAME_INTERVAL), false);
778
            //obs_data_set_int(data, AMF_H264_IDR_PERIOD, 120);
779
            //obs_data_set_int(data, AMF_H264_HEADER_INSERTION_SPACING, 0);
780
-           //obs_data_set_int(data, AMF_H264_BPICTURE_PATTERN, 0);
781
-           //obs_data_set_int(data, AMF_H264_BPICTURE_REFERENCE, 0);
782
+           //obs_data_set_int(data, AMF_H264_BFRAME_PATTERN, 0);
783
+           //obs_data_set_int(data, AMF_H264_BFRAME_REFERENCE, 0);
784
            //obs_data_set_int(data, AMF_H264_SLICESPERFRAME, 0);
785
            //obs_data_set_int(data, AMF_H264_INTRAREFRESHNUMMBSPERSLOT, 0);
786
 
787
@@ -912,19 +1015,40 @@
788
    }
789
    #pragma endregion Presets
790
 
791
-   #pragma region Device Capabilities
792
-   const char* deviceId = obs_data_get_string(data, AMF_H264_DEVICE);
793
-   auto device = Plugin::API::APIBase::GetDeviceForUniqueId(deviceId);
794
-   auto caps = Plugin::AMD::VCECapabilities::GetInstance();
795
-   auto devCaps = caps->GetDeviceCaps(device, VCEEncoderType_AVC);
796
-   #pragma endregion Device Capabilities
797
+   #pragma region Video API
798
+   const char *lastVideoAPI = obs_data_get_string(data, "last" vstr(AMF_H264_VIDEOAPI)),
799
+       *curVideoAPI = obs_data_get_string(data, AMF_H264_VIDEOAPI);
800
+   if (strcmp(curVideoAPI, "") == 0) {
801
+       p = obs_properties_get(props, AMF_H264_VIDEOAPI);
802
+       //fill_api_list(p);
803
+
804
+       obs_data_set_string(data, AMF_H264_VIDEOAPI,
805
+           obs_property_list_item_string(p, 0));
806
+       curVideoAPI = obs_data_get_string(data, AMF_H264_VIDEOAPI);
807
+   }
808
+   if ((strcmp(lastVideoAPI, curVideoAPI) != 0)
809
+       || (strcmp(curVideoAPI, "") == 0)) {
810
+       obs_data_set_string(data, "last" vstr(AMF_H264_VIDEOAPI), curVideoAPI);
811
+       fill_device_list(obs_properties_get(props, AMF_H264_VIDEOADAPTER), curVideoAPI);
812
+
813
+       // Reset Video Adapter to first in list.
814
+       obs_data_set_int(data, AMF_H264_VIDEOADAPTER,
815
+           obs_property_list_item_int(obs_properties_get(props, AMF_H264_VIDEOADAPTER), 0));
816
+   }
817
+   #pragma endregion Video API
818
+
819
+   #pragma region Video Adapter & Capabilities
820
+   VCEDeviceCapabilities devCaps;
821
+   int64_t lastAdapterId = obs_data_get_int(data, "last" vstr(AMF_H264_VIDEOADAPTER)),
822
+       curAdapterId = obs_data_get_int(data, AMF_H264_VIDEOADAPTER);
823
+   {
824
+       auto api = Plugin::API::Base::GetAPIByName(obs_data_get_string(data, AMF_H264_VIDEOAPI));
825
+       auto adapter = api->GetAdapterById(curAdapterId & UINT_MAX, (curAdapterId >> 32) & UINT_MAX);
826
+       devCaps = Plugin::AMD::VCECapabilities::GetInstance()->GetAdapterCapabilities(api, adapter, VCEEncoderType_AVC);
827
+   }
828
+   if (lastAdapterId != curAdapterId) {
829
+       obs_data_set_int(data, "last" vstr(AMF_H264_VIDEOADAPTER), curAdapterId);
830
 
831
-   #pragma region Rebuild UI
832
-   bool unlocked = obs_data_get_bool(data, AMF_H264_UNLOCK_PROPERTIES);
833
-   bool lastUnlocked = obs_data_get_bool(data, "last" vstr(AMF_H264_UNLOCK_PROPERTIES));
834
-   const char* lastDeviceId = obs_data_get_string(data, "last" vstr(AMF_H264_DEVICE));
835
-   if (strcmp(lastDeviceId, deviceId) != 0 || (unlocked != lastUnlocked)) {
836
-       #pragma region Static Properties
837
        #pragma region Profile
838
        p = obs_properties_get(props, AMF_H264_PROFILE);
839
        obs_property_list_clear(p);
840
@@ -940,6 +1064,7 @@
841
                break;
842
        }
843
        #pragma endregion Profile
844
+
845
        #pragma region Profile Level
846
        p = obs_properties_get(props, AMF_H264_PROFILELEVEL);
847
        obs_property_list_clear(p);
848
@@ -986,70 +1111,44 @@
849
                obs_property_list_add_int(p, "1.0", VCEProfileLevel_10);
850
        }
851
        #pragma endregion Profile Level
852
-       #pragma endregion Static Properties
853
-
854
-       #pragma region Unlockable Stuff
855
-       // Store values.
856
-       uint64_t bitrateTarget = obs_data_get_int(data, AMF_H264_BITRATE_TARGET),
857
-           bitratePeak = obs_data_get_int(data, AMF_H264_BITRATE_PEAK),
858
-           vbvBufferSize = obs_data_get_int(data, AMF_H264_VBVBUFFER_SIZE);
859
 
860
-       // Set proper limits
861
-       uint32_t limitDivisor = unlocked ? 1 : 1000;
862
        obs_property_int_set_limits(obs_properties_get(props, AMF_H264_BITRATE_TARGET),
863
-           10000 / limitDivisor,
864
-           devCaps.maxBitrate / limitDivisor,
865
-           1);
866
+           10, devCaps.maxBitrate / 1000, 1);
867
        obs_property_int_set_limits(obs_properties_get(props, AMF_H264_BITRATE_PEAK),
868
-           10000 / limitDivisor,
869
-           devCaps.maxBitrate / limitDivisor,
870
-           1);
871
+           10, devCaps.maxBitrate / 1000, 1);
872
        obs_property_int_set_limits(obs_properties_get(props, AMF_H264_VBVBUFFER_SIZE),
873
-           1000 / limitDivisor,
874
-           100000000 / limitDivisor,
875
-           1);
876
+           1, 100000, 1);
877
        obs_property_float_set_limits(obs_properties_get(props, AMF_H264_KEYFRAME_INTERVAL),
878
-           unlocked ? 0 : 1,
879
-           100,
880
-           1);
881
+           1.0 / 144.0, 30, 1.0 / 144.0);
882
        obs_property_int_set_limits(obs_properties_get(props, AMF_H264_IDR_PERIOD),
883
-           unlocked ? 0 : 1,
884
-           1000,
885
-           1);
886
-
887
-       // Restore values.
888
-       uint64_t valDivisor = (lastUnlocked && !unlocked ? 1000 : 1);
889
-       uint64_t valMultiplier = (unlocked && !lastUnlocked ? 1000 : 1);
890
+           1, 1000, 1);
891
 
892
-       obs_data_set_int(data, AMF_H264_BITRATE_TARGET, (bitrateTarget * valMultiplier) / valDivisor);
893
-       obs_data_set_int(data, AMF_H264_BITRATE_PEAK, (bitratePeak * valMultiplier) / valDivisor);
894
-       obs_data_set_int(data, AMF_H264_VBVBUFFER_SIZE, (vbvBufferSize * valMultiplier) / valDivisor);
895
-       #pragma endregion Unlockable Stuff
896
-
897
-       obs_data_set_bool(data, "last" vstr(AMF_H264_UNLOCK_PROPERTIES), unlocked);
898
-       obs_data_set_string(data, "last" vstr(AMF_H264_DEVICE), deviceId);
899
-       result = true;
900
+       // Experimental
901
+       obs_property_int_set_limits(obs_properties_get(props, AMF_H264_MAXIMUMREFERENCEFRAMES),
902
+           devCaps.minReferenceFrames, devCaps.maxReferenceFrames, 1);
903
    }
904
-   #pragma endregion Rebuild UI
905
+   #pragma endregion Video Adapter
906
 
907
    #pragma region View Mode
908
-   uint32_t view = (uint32_t)obs_data_get_int(data, AMF_H264_VIEW);
909
-   bool vis_basic = view >= ViewMode::Basic,
910
-       vis_advanced = view >= ViewMode::Advanced,
911
-       vis_expert = view >= ViewMode::Expert,
912
-       vis_master = view >= ViewMode::Master;
913
-
914
-   uint32_t lastView = (uint32_t)obs_data_get_int(data, "last" vstr(AMF_H264_VIEW));
915
-   if (lastView != view) {
916
-       obs_data_set_int(data, "last" vstr(AMF_H264_VIEW), view);
917
+   uint32_t lastView = (uint32_t)obs_data_get_int(data, "last" vstr(AMF_H264_VIEW)),
918
+       curView = (uint32_t)obs_data_get_int(data, AMF_H264_VIEW);
919
+   if (lastView != curView) {
920
+       obs_data_set_int(data, "last" vstr(AMF_H264_VIEW), curView);
921
        result = true;
922
    }
923
 
924
+   bool vis_basic = curView >= ViewMode::Basic,
925
+       vis_advanced = curView >= ViewMode::Advanced,
926
+       vis_expert = curView >= ViewMode::Expert,
927
+       vis_master = curView >= ViewMode::Master;
928
+
929
    #pragma region Basic
930
    const char* basicProps[] = {
931
+       AMF_H264_PRESET,
932
        AMF_H264_QUALITY_PRESET,
933
        AMF_H264_PROFILE,
934
        AMF_H264_RATECONTROLMETHOD,
935
+       AMF_H264_VIEW,
936
        AMF_H264_DEBUG,
937
    };
938
    for (auto prop : basicProps) {
939
@@ -1063,8 +1162,9 @@
940
    const char* advancedProps[] = {
941
        AMF_H264_VBVBUFFER,
942
        AMF_H264_FRAMESKIPPING,
943
+       AMF_H264_ENFORCEHRDCOMPATIBILITY,
944
        AMF_H264_DEBLOCKINGFILTER,
945
-       AMF_H264_DEVICE,
946
+       AMF_H264_VIDEOAPI,
947
    };
948
    for (auto prop : advancedProps) {
949
        obs_property_set_visible(obs_properties_get(props, prop), vis_advanced);
950
@@ -1076,11 +1176,8 @@
951
    #pragma region Expert
952
    const char* expertProps[] = {
953
        AMF_H264_PROFILELEVEL,
954
-       AMF_H264_CODINGTYPE,
955
        AMF_H264_VBVBUFFER_FULLNESS,
956
-       AMF_H264_ENFORCEHRDCOMPATIBILITY,
957
        AMF_H264_MOTIONESTIMATION,
958
-       AMF_H264_USE_OPENCL,
959
    };
960
    for (auto prop : expertProps) {
961
        obs_property_set_visible(obs_properties_get(props, prop), vis_expert);
962
@@ -1092,14 +1189,25 @@
963
    #pragma region Master
964
    const char* masterProps[] = {
965
        AMF_H264_USAGE,
966
-       AMF_H264_MAXIMUMLTRFRAMES,
967
        AMF_H264_MAXIMUMACCESSUNITSIZE,
968
        AMF_H264_IDR_PERIOD,
969
        AMF_H264_HEADER_INSERTION_SPACING,
970
-       AMF_H264_SLICESPERFRAME,
971
-       AMF_H264_INTRAREFRESHNUMMBSPERSLOT,
972
        AMF_H264_SCANTYPE,
973
-       AMF_H264_UNLOCK_PROPERTIES,
974
+       AMF_H264_MAXIMUMLTRFRAMES,
975
+       AMF_H264_CODINGTYPE,
976
+       AMF_H264_SLICESPERFRAME,
977
+       AMF_H264_SLICEMODE,
978
+       AMF_H264_MAXIMUMSLICESIZE,
979
+       AMF_H264_SLICECONTROLMODE,
980
+       AMF_H264_SLICECONTROLSIZE,
981
+       AMF_H264_INTRAREFRESH_NUMBEROFSTRIPES,
982
+       AMF_H264_INTRAREFRESH_MACROBLOCKSPERSLOT,
983
+       AMF_H264_WAITFORTASK,
984
+       AMF_H264_PREANALYSISPASS,
985
+       AMF_H264_VBAQ,
986
+       AMF_H264_GOPSIZE,
987
+       AMF_H264_GOPALIGNMENT,
988
+       AMF_H264_MAXIMUMREFERENCEFRAMES,
989
    };
990
    for (auto prop : masterProps) {
991
        obs_property_set_visible(obs_properties_get(props, prop), vis_master);
992
@@ -1112,11 +1220,43 @@
993
    uint32_t ltrFrames = (uint32_t)obs_data_get_int(data, AMF_H264_MAXIMUMLTRFRAMES);
994
    bool usingLTRFrames = ltrFrames > 0;
995
 
996
-   // Keyframe Interval
997
+   // Key-frame Interval
998
    obs_property_set_visible(obs_properties_get(props, AMF_H264_KEYFRAME_INTERVAL), !vis_master);
999
    if (vis_master)
1000
        obs_data_default_single(props, data, AMF_H264_KEYFRAME_INTERVAL);
1001
 
1002
+   #pragma region B-Frames
1003
+   /// Pattern
1004
+   obs_property_set_visible(obs_properties_get(props, AMF_H264_BFRAME_PATTERN), vis_advanced && !usingLTRFrames && devCaps.supportsBFrames);
1005
+   if (!vis_advanced || usingLTRFrames || !devCaps.supportsBFrames)
1006
+       obs_data_default_single(props, data, AMF_H264_BFRAME_PATTERN);
1007
+   bool lastUsingBFrames = obs_data_get_int(data, "last" vstr(AMF_H264_BFRAME_PATTERN)) != 0,
1008
+       usingBFrames = obs_data_get_int(data, AMF_H264_BFRAME_PATTERN) != 0;
1009
+   if (usingBFrames != lastUsingBFrames) {
1010
+       obs_data_set_int(data, "last" vstr(AMF_H264_BFRAME_PATTERN), obs_data_get_int(data, AMF_H264_BFRAME_PATTERN));
1011
+       result = true;
1012
+   }
1013
+
1014
+   /// Reference
1015
+   obs_property_set_visible(obs_properties_get(props, AMF_H264_BFRAME_REFERENCE), vis_advanced && !usingLTRFrames && usingBFrames && devCaps.supportsBFrames);
1016
+   if (!vis_advanced || usingLTRFrames || !usingBFrames || !devCaps.supportsBFrames)
1017
+       obs_data_default_single(props, data, AMF_H264_BFRAME_REFERENCE);
1018
+   bool lastUsingBFrameReference = obs_data_get_int(data, "last" vstr(AMF_H264_BFRAME_REFERENCE)) != 0,
1019
+       usingBFrameReference = obs_data_get_int(data, AMF_H264_BFRAME_REFERENCE) == 1;
1020
+   if (usingBFrameReference != lastUsingBFrameReference) {
1021
+       obs_data_set_int(data, "last" vstr(AMF_H264_BFRAME_REFERENCE), obs_data_get_int(data, AMF_H264_BFRAME_REFERENCE));
1022
+       result = true;
1023
+   }
1024
+
1025
+   /// QP Delta
1026
+   obs_property_set_visible(obs_properties_get(props, AMF_H264_BFRAME_DELTAQP), vis_advanced && usingBFrames && devCaps.supportsBFrames);
1027
+   if (!vis_advanced || !usingBFrames || !devCaps.supportsBFrames)
1028
+       obs_data_default_single(props, data, AMF_H264_BFRAME_DELTAQP);
1029
+   obs_property_set_visible(obs_properties_get(props, AMF_H264_BFRAME_REFERENCEDELTAQP), vis_advanced && usingBFrames && usingBFrameReference && devCaps.supportsBFrames);
1030
+   if (!vis_advanced || !usingBFrames || !usingBFrameReference || !devCaps.supportsBFrames)
1031
+       obs_data_default_single(props, data, AMF_H264_BFRAME_REFERENCEDELTAQP);
1032
+   #pragma endregion B-Frames
1033
+
1034
    #pragma region Rate Control
1035
    bool vis_rcm_bitrate_target = false,
1036
        vis_rcm_bitrate_peak = false,
1037
@@ -1124,8 +1264,13 @@
1038
        vis_rcm_qp_b = false,
1039
        vis_rcm_fillerdata = false;
1040
 
1041
-   VCERateControlMethod rcm = (VCERateControlMethod)obs_data_get_int(data, AMF_H264_RATECONTROLMETHOD);
1042
-   switch (rcm) {
1043
+   VCERateControlMethod lastRCM = (VCERateControlMethod)obs_data_get_int(data, "last" vstr(AMF_H264_RATECONTROLMETHOD)),
1044
+       curRCM = (VCERateControlMethod)obs_data_get_int(data, AMF_H264_RATECONTROLMETHOD);
1045
+   if (lastRCM != curRCM) {
1046
+       obs_data_set_int(data, "last" vstr(AMF_H264_RATECONTROLMETHOD), curRCM);
1047
+       result = true;
1048
+   }
1049
+   switch (curRCM) {
1050
        case VCERateControlMethod_ConstantBitrate:
1051
            vis_rcm_bitrate_target = true;
1052
            vis_rcm_fillerdata = true;
1053
@@ -1140,16 +1285,10 @@
1054
            break;
1055
        case VCERateControlMethod_ConstantQP:
1056
            vis_rcm_qp = true;
1057
-           vis_rcm_qp_b = (!usingLTRFrames) && devCaps.supportsBFrames;
1058
+           vis_rcm_qp_b = (!usingLTRFrames) && devCaps.supportsBFrames && usingBFrames;
1059
            break;
1060
    }
1061
 
1062
-   VCERateControlMethod lastRCM = (VCERateControlMethod)obs_data_get_int(data, "last" vstr(AMF_H264_RATECONTROLMETHOD));
1063
-   if (lastRCM != rcm) {
1064
-       obs_data_set_int(data, "last" vstr(AMF_H264_RATECONTROLMETHOD), rcm);
1065
-       result = true;
1066
-   }
1067
-
1068
    /// Bitrate
1069
    obs_property_set_visible(obs_properties_get(props, AMF_H264_BITRATE_TARGET), vis_rcm_bitrate_target);
1070
    if (!vis_rcm_bitrate_target)
1071
@@ -1182,6 +1321,7 @@
1072
    if (!vis_rcm_fillerdata)
1073
        obs_data_default_single(props, data, AMF_H264_FILLERDATA);
1074
    #pragma endregion Rate Control
1075
+
1076
    #pragma region VBV Buffer
1077
    uint32_t vbvBufferMode = (uint32_t)obs_data_get_int(data, AMF_H264_VBVBUFFER);
1078
    bool vbvBufferVisible = vis_advanced;
1079
@@ -1194,47 +1334,22 @@
1080
 
1081
    obs_property_set_visible(obs_properties_get(props, AMF_H264_VBVBUFFER_STRICTNESS), vbvBufferVisible && (vbvBufferMode == 0));
1082
    obs_property_set_visible(obs_properties_get(props, AMF_H264_VBVBUFFER_SIZE), vbvBufferVisible && (vbvBufferMode == 1));
1083
-   if (!vbvBufferVisible) {
1084
-       if (vbvBufferMode == 0) {
1085
-           obs_data_default_single(props, data, AMF_H264_VBVBUFFER_SIZE);
1086
-       } else if (vbvBufferMode == 1) {
1087
-           obs_data_default_single(props, data, AMF_H264_VBVBUFFER_STRICTNESS);
1088
-       }
1089
-   }
1090
+   if (!vbvBufferVisible || vbvBufferMode == 0)
1091
+       obs_data_default_single(props, data, AMF_H264_VBVBUFFER_SIZE);
1092
+   if (!vbvBufferVisible || vbvBufferMode == 1)
1093
+       obs_data_default_single(props, data, AMF_H264_VBVBUFFER_STRICTNESS);
1094
    #pragma endregion VBV Buffer
1095
-   #pragma region B-Frames
1096
-   /// Pattern
1097
-   obs_property_set_visible(obs_properties_get(props, AMF_H264_BPICTURE_PATTERN), vis_advanced && !usingLTRFrames && devCaps.supportsBFrames);
1098
-   if (!vis_advanced || usingLTRFrames || !devCaps.supportsBFrames)
1099
-       obs_data_default_single(props, data, AMF_H264_BPICTURE_PATTERN);
1100
-   bool usingBPictures = obs_data_get_int(data, AMF_H264_BPICTURE_PATTERN) != 0;
1101
 
1102
-   bool lastUsingBPictures = obs_data_get_int(data, "last" vstr(AMF_H264_BPICTURE_PATTERN)) != 0;
1103
-   if (usingBPictures != lastUsingBPictures) {
1104
-       obs_data_set_int(data, "last" vstr(AMF_H264_BPICTURE_PATTERN), obs_data_get_int(data, AMF_H264_BPICTURE_PATTERN));
1105
-       result = true;
1106
-   }
1107
+   bool isnothostmode = strcmp(obs_data_get_string(data, AMF_H264_VIDEOAPI), "Host") != 0;
1108
+   /// Video Adapter
1109
+   obs_property_set_visible(obs_properties_get(props, AMF_H264_VIDEOADAPTER), vis_advanced && isnothostmode);
1110
+   if (!vis_advanced || !isnothostmode)
1111
+       obs_data_default_single(props, data, AMF_H264_VIDEOADAPTER);
1112
+   /// OpenCL
1113
+   obs_property_set_visible(obs_properties_get(props, AMF_H264_OPENCL), vis_advanced && isnothostmode);
1114
+   if (!vis_advanced || !isnothostmode)
1115
+       obs_data_default_single(props, data, AMF_H264_OPENCL);
1116
 
1117
-   /// Reference
1118
-   obs_property_set_visible(obs_properties_get(props, AMF_H264_BPICTURE_REFERENCE), vis_advanced && !usingLTRFrames && usingBPictures && devCaps.supportsBFrames);
1119
-   if (!vis_advanced || usingLTRFrames || !usingBPictures || !devCaps.supportsBFrames)
1120
-       obs_data_default_single(props, data, AMF_H264_BPICTURE_REFERENCE);
1121
-   bool usingBPictureReference = obs_data_get_int(data, AMF_H264_BPICTURE_REFERENCE) == 1;
1122
-
1123
-   bool lastUsingBPictureReference = obs_data_get_int(data, "last" vstr(AMF_H264_BPICTURE_REFERENCE)) != 0;
1124
-   if (usingBPictureReference != lastUsingBPictureReference) {
1125
-       obs_data_set_int(data, "last" vstr(AMF_H264_BPICTURE_REFERENCE), obs_data_get_int(data, AMF_H264_BPICTURE_REFERENCE));
1126
-       result = true;
1127
-   }
1128
-
1129
-   /// QP Delta
1130
-   obs_property_set_visible(obs_properties_get(props, AMF_H264_QP_BPICTURE_DELTA), vis_advanced && usingBPictures && devCaps.supportsBFrames);
1131
-   if (!vis_advanced || !usingBPictures || !devCaps.supportsBFrames)
1132
-       obs_data_default_single(props, data, AMF_H264_QP_BPICTURE_DELTA);
1133
-   obs_property_set_visible(obs_properties_get(props, AMF_H264_QP_REFERENCE_BPICTURE_DELTA), vis_advanced && usingBPictures && usingBPictureReference && devCaps.supportsBFrames);
1134
-   if (!vis_advanced || !usingBPictures || !usingBPictureReference || !devCaps.supportsBFrames)
1135
-       obs_data_default_single(props, data, AMF_H264_QP_REFERENCE_BPICTURE_DELTA);
1136
-   #pragma endregion B-Frames
1137
    #pragma endregion Special Logic
1138
    #pragma endregion View Mode
1139
 
1140
@@ -1307,36 +1422,31 @@
1141
            surfFormat = VCEColorFormat_GRAY;
1142
            break;
1143
    }
1144
-   m_VideoEncoder = new VCEEncoder(VCEEncoderType_AVC,
1145
-       std::string(obs_data_get_string(data, AMF_H264_DEVICE)),
1146
-       !!obs_data_get_int(data, AMF_H264_USE_OPENCL),
1147
-       surfFormat);
1148
-   m_VideoEncoder->SetColorProfile(voi->colorspace == VIDEO_CS_709 ? VCEColorProfile_709 : VCEColorProfile_601);
1149
-   m_VideoEncoder->SetFullColorRangeEnabled(voi->range == VIDEO_RANGE_FULL);
1150
+   m_VideoEncoder = new VCEEncoder(VCEEncoderType_AVC, obs_data_get_string(data, AMF_H264_VIDEOAPI),
1151
+       obs_data_get_int(data, AMF_H264_VIDEOADAPTER), !!obs_data_get_int(data, AMF_H264_OPENCL), surfFormat);
1152
 
1153
    /// Static Properties
1154
    m_VideoEncoder->SetUsage((VCEUsage)obs_data_get_int(data, AMF_H264_USAGE));
1155
    m_VideoEncoder->SetQualityPreset((VCEQualityPreset)obs_data_get_int(data, AMF_H264_QUALITY_PRESET));
1156
 
1157
-   /// Framesize & Framerate
1158
-   m_VideoEncoder->SetFrameSize(m_cfgWidth, m_cfgHeight);
1159
+   /// Frame
1160
+   m_VideoEncoder->SetColorProfile(voi->colorspace == VIDEO_CS_709 ? VCEColorProfile_709 : VCEColorProfile_601);
1161
+   try { m_VideoEncoder->SetFullRangeColorEnabled(voi->range == VIDEO_RANGE_FULL); } catch (...) {}
1162
+   m_VideoEncoder->SetResolution(m_cfgWidth, m_cfgHeight);
1163
    m_VideoEncoder->SetFrameRate(m_cfgFPSnum, m_cfgFPSden);
1164
+   m_VideoEncoder->SetScanType((VCEScanType)obs_data_get_int(data, AMF_H264_SCANTYPE)); /// Progressive or Interlaced
1165
 
1166
    /// Profile & Level
1167
    m_VideoEncoder->SetProfile((VCEProfile)obs_data_get_int(data, AMF_H264_PROFILE));
1168
    m_VideoEncoder->SetProfileLevel((VCEProfileLevel)obs_data_get_int(data, AMF_H264_PROFILELEVEL));
1169
 
1170
-   /// LTR Stuff
1171
+   #pragma region Experimental
1172
+   /// Long Term Reference
1173
    if ((uint32_t)obs_data_get_int(data, AMF_H264_MAXIMUMLTRFRAMES) > 0)
1174
-       m_VideoEncoder->SetBPicturePattern(VCEBPicturePattern_None);
1175
+       m_VideoEncoder->SetBFramePattern(VCEBFramePattern_None);
1176
    m_VideoEncoder->SetMaximumLongTermReferenceFrames((uint32_t)obs_data_get_int(data, AMF_H264_MAXIMUMLTRFRAMES));
1177
 
1178
-   /// Miscellaneous Properties
1179
-   m_VideoEncoder->SetScanType((VCEScanType)obs_data_get_int(data, AMF_H264_SCANTYPE));
1180
-   m_VideoEncoder->SetCodingType((VCECodingType)obs_data_get_int(data, AMF_H264_CODINGTYPE));
1181
-   //m_VideoEncoder->SetRateControlPreanalysisEnabled(true);
1182
-   //m_VideoEncoder->SetWaitForTaskEnabled(true);
1183
-   //m_VideoEncoder->SetMaximumNumberOfReferenceFrames(VCECapabilities::GetInstance()->GetEncoderCaps(VCEEncoderType_AVC)->maxReferenceFrames);
1184
+   #pragma endregion Experimental
1185
 
1186
    // OBS - Enforce Streaming Service Restrictions
1187
    #pragma region OBS - Enforce Streaming Service Restrictions
1188
@@ -1344,21 +1454,31 @@
1189
        // Profile
1190
        const char* p_str = obs_data_get_string(data, "profile");
1191
        if (strcmp(p_str, "") != 0) {
1192
-           if (strcmp(p_str, "baseline")) {
1193
+           if (strcmp(p_str, "constrained_baseline")) {
1194
+               m_VideoEncoder->SetProfile(VCEProfile_ConstrainedBaseline);
1195
+           } else if (strcmp(p_str, "baseline")) {
1196
                m_VideoEncoder->SetProfile(VCEProfile_Baseline);
1197
            } else if (strcmp(p_str, "main")) {
1198
                m_VideoEncoder->SetProfile(VCEProfile_Main);
1199
+           } else if (strcmp(p_str, "constrained_high")) {
1200
+               m_VideoEncoder->SetProfile(VCEProfile_ConstrainedHigh);
1201
            } else if (strcmp(p_str, "high")) {
1202
                m_VideoEncoder->SetProfile(VCEProfile_High);
1203
            }
1204
        } else {
1205
            switch (m_VideoEncoder->GetProfile()) {
1206
+               case VCEProfile_ConstrainedBaseline:
1207
+                   obs_data_set_string(data, "profile", "constrained_baseline");
1208
+                   break;
1209
                case VCEProfile_Baseline:
1210
                    obs_data_set_string(data, "profile", "baseline");
1211
                    break;
1212
                case VCEProfile_Main:
1213
                    obs_data_set_string(data, "profile", "main");
1214
                    break;
1215
+               case VCEProfile_ConstrainedHigh:
1216
+                   obs_data_set_string(data, "profile", "constrained_high");
1217
+                   break;
1218
                case VCEProfile_High:
1219
                    obs_data_set_string(data, "profile", "high");
1220
                    break;
1221
@@ -1419,81 +1539,101 @@
1222
 
1223
 bool Plugin::Interface::H264Interface::update(obs_data_t* data) {
1224
    #pragma region Device Capabilities
1225
-   const char* deviceId = obs_data_get_string(data, AMF_H264_DEVICE);
1226
-   auto device = Plugin::API::APIBase::GetDeviceForUniqueId(deviceId);
1227
-   auto caps = Plugin::AMD::VCECapabilities::GetInstance();
1228
-   auto devCaps = caps->GetDeviceCaps(device, VCEEncoderType_AVC);
1229
+   auto api = Plugin::API::Base::GetAPIByName(obs_data_get_string(data, AMF_H264_VIDEOAPI));
1230
+   int64_t adapterId = obs_data_get_int(data, AMF_H264_VIDEOADAPTER);
1231
+   auto adapter = api->GetAdapterById(adapterId & UINT_MAX, (adapterId >> 32) & UINT_MAX);
1232
+   auto devCaps = Plugin::AMD::VCECapabilities::GetInstance()->GetAdapterCapabilities(api, adapter, VCEEncoderType_AVC);
1233
    #pragma endregion Device Capabilities
1234
 
1235
-   double_t framerate = (double_t)m_VideoEncoder->GetFrameRate().first / (double_t)m_VideoEncoder->GetFrameRate().second;
1236
-   int32_t bitrateMultiplier = obs_data_get_bool(data, AMF_H264_UNLOCK_PROPERTIES) ? 1 : 1000;
1237
-
1238
+   #pragma region Rate Control
1239
    // Rate Control Properties
1240
    m_VideoEncoder->SetRateControlMethod((VCERateControlMethod)obs_data_get_int(data, AMF_H264_RATECONTROLMETHOD));
1241
    m_VideoEncoder->SetMinimumQP((uint8_t)obs_data_get_int(data, AMF_H264_QP_MINIMUM));
1242
    m_VideoEncoder->SetMaximumQP((uint8_t)obs_data_get_int(data, AMF_H264_QP_MAXIMUM));
1243
    switch ((VCERateControlMethod)obs_data_get_int(data, AMF_H264_RATECONTROLMETHOD)) {
1244
        case VCERateControlMethod_ConstantBitrate:
1245
-           m_VideoEncoder->SetTargetBitrate((uint32_t)obs_data_get_int(data, AMF_H264_BITRATE_TARGET) * bitrateMultiplier);
1246
+           m_VideoEncoder->SetTargetBitrate((uint32_t)obs_data_get_int(data, AMF_H264_BITRATE_TARGET) * 1000);
1247
            m_VideoEncoder->SetPeakBitrate(m_VideoEncoder->GetTargetBitrate());
1248
            break;
1249
        case VCERateControlMethod_VariableBitrate_PeakConstrained:
1250
-           m_VideoEncoder->SetTargetBitrate((uint32_t)obs_data_get_int(data, AMF_H264_BITRATE_TARGET) * bitrateMultiplier);
1251
-           m_VideoEncoder->SetPeakBitrate((uint32_t)obs_data_get_int(data, AMF_H264_BITRATE_PEAK) * bitrateMultiplier);
1252
+           m_VideoEncoder->SetTargetBitrate((uint32_t)obs_data_get_int(data, AMF_H264_BITRATE_TARGET) * 1000);
1253
+           m_VideoEncoder->SetPeakBitrate((uint32_t)obs_data_get_int(data, AMF_H264_BITRATE_PEAK) * 1000);
1254
            break;
1255
        case VCERateControlMethod_VariableBitrate_LatencyConstrained:
1256
-           m_VideoEncoder->SetTargetBitrate((uint32_t)obs_data_get_int(data, AMF_H264_BITRATE_TARGET) * bitrateMultiplier);
1257
-           m_VideoEncoder->SetPeakBitrate((uint32_t)obs_data_get_int(data, AMF_H264_BITRATE_PEAK) * bitrateMultiplier);
1258
+           m_VideoEncoder->SetTargetBitrate((uint32_t)obs_data_get_int(data, AMF_H264_BITRATE_TARGET) * 1000);
1259
+           m_VideoEncoder->SetPeakBitrate((uint32_t)obs_data_get_int(data, AMF_H264_BITRATE_PEAK) * 1000);
1260
            break;
1261
        case VCERateControlMethod_ConstantQP:
1262
            m_VideoEncoder->SetIFrameQP((uint8_t)obs_data_get_int(data, AMF_H264_QP_IFRAME));
1263
            m_VideoEncoder->SetPFrameQP((uint8_t)obs_data_get_int(data, AMF_H264_QP_PFRAME));
1264
            try {
1265
                m_VideoEncoder->SetBFrameQP((uint8_t)obs_data_get_int(data, AMF_H264_QP_BFRAME));
1266
-           } catch (...) {}
1267
+           } catch (std::exception e) {} catch (...) {}
1268
            break;
1269
    }
1270
    if (obs_data_get_int(data, AMF_H264_VBVBUFFER) == 0) {
1271
        m_VideoEncoder->SetVBVBufferAutomatic(obs_data_get_double(data, AMF_H264_VBVBUFFER_STRICTNESS) / 100.0);
1272
    } else {
1273
-       m_VideoEncoder->SetVBVBufferSize((uint32_t)obs_data_get_int(data, AMF_H264_VBVBUFFER_SIZE) * bitrateMultiplier);
1274
+       m_VideoEncoder->SetVBVBufferSize((uint32_t)obs_data_get_int(data, AMF_H264_VBVBUFFER_SIZE) * 1000);
1275
    }
1276
    m_VideoEncoder->SetInitialVBVBufferFullness(obs_data_get_double(data, AMF_H264_VBVBUFFER_FULLNESS) / 100.0);
1277
-   m_VideoEncoder->SetEnforceHRDRestrictionsEnabled(obs_data_get_int(data, AMF_H264_ENFORCEHRDCOMPATIBILITY) == 1);
1278
    m_VideoEncoder->SetFillerDataEnabled(obs_data_get_int(data, AMF_H264_FILLERDATA) == 1);
1279
    m_VideoEncoder->SetFrameSkippingEnabled(obs_data_get_int(data, AMF_H264_FRAMESKIPPING) == 1);
1280
-   if (obs_data_get_int(data, AMF_H264_MAXIMUMACCESSUNITSIZE) != 0)
1281
-       m_VideoEncoder->SetMaximumAccessUnitSize((uint32_t)obs_data_get_int(data, AMF_H264_MAXIMUMACCESSUNITSIZE));
1282
+   m_VideoEncoder->SetEnforceHRDRestrictionsEnabled(obs_data_get_int(data, AMF_H264_ENFORCEHRDCOMPATIBILITY) == 1);
1283
+   #pragma endregion Rate Control
1284
 
1285
-   // Picture Control Properties
1286
+   // Key-frame Interval
1287
+   double_t framerate = (double_t)m_VideoEncoder->GetFrameRate().first / (double_t)m_VideoEncoder->GetFrameRate().second;
1288
    if (obs_data_get_int(data, AMF_H264_VIEW) == ViewMode::Master)
1289
        m_VideoEncoder->SetIDRPeriod((uint32_t)obs_data_get_int(data, AMF_H264_IDR_PERIOD));
1290
    else
1291
        m_VideoEncoder->SetIDRPeriod(max((uint32_t)(obs_data_get_double(data, AMF_H264_KEYFRAME_INTERVAL) * framerate), 1));
1292
-   if (obs_data_get_int(data, AMF_H264_HEADER_INSERTION_SPACING) != 0)
1293
-       m_VideoEncoder->SetHeaderInsertionSpacing((uint32_t)obs_data_get_int(data, AMF_H264_HEADER_INSERTION_SPACING));
1294
-   m_VideoEncoder->SetDeblockingFilterEnabled(!!obs_data_get_int(data, AMF_H264_DEBLOCKINGFILTER));
1295
+
1296
+   #pragma region B-Frames
1297
    if (devCaps.supportsBFrames) {
1298
        try {
1299
-           m_VideoEncoder->SetBPicturePattern((VCEBPicturePattern)obs_data_get_int(data, AMF_H264_BPICTURE_PATTERN));
1300
-           m_VideoEncoder->SetBPictureReferenceEnabled(!!obs_data_get_int(data, AMF_H264_BPICTURE_REFERENCE));
1301
-       } catch (...) {}
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->GetBPicturePattern() != VCEBPicturePattern_None) {
1307
-               m_VideoEncoder->SetBPictureDeltaQP((int8_t)obs_data_get_int(data, AMF_H264_QP_BPICTURE_DELTA));
1308
-               if (m_VideoEncoder->IsBPictureReferenceEnabled())
1309
-                   m_VideoEncoder->SetReferenceBPictureDeltaQP((int8_t)obs_data_get_int(data, AMF_H264_QP_REFERENCE_BPICTURE_DELTA));
1310
+           if (m_VideoEncoder->GetBFramePattern() != VCEBFramePattern_None) {
1311
+               m_VideoEncoder->SetBFrameDeltaQP((int8_t)obs_data_get_int(data, AMF_H264_BFRAME_DELTAQP));
1312
+               if (m_VideoEncoder->IsBFrameReferenceEnabled())
1313
+                   m_VideoEncoder->SetBFrameReferenceDeltaQP((int8_t)obs_data_get_int(data, AMF_H264_BFRAME_REFERENCEDELTAQP));
1314
            }
1315
-       } catch (...) {}
1316
+       } catch (std::exception e) {} catch (...) {}
1317
    }
1318
-   if (obs_data_get_int(data, AMF_H264_SLICESPERFRAME) != 0)
1319
-       m_VideoEncoder->SetSlicesPerFrame((uint32_t)obs_data_get_int(data, AMF_H264_SLICESPERFRAME));
1320
-   if (obs_data_get_int(data, AMF_H264_INTRAREFRESHNUMMBSPERSLOT) != 0)
1321
-       m_VideoEncoder->SetIntraRefreshMBsNumberPerSlot((uint32_t)obs_data_get_int(data, AMF_H264_INTRAREFRESHNUMMBSPERSLOT));
1322
+   #pragma endregion B-Frames
1323
+
1324
+   m_VideoEncoder->SetDeblockingFilterEnabled(!!obs_data_get_int(data, AMF_H264_DEBLOCKINGFILTER));
1325
 
1326
-   // Miscellaneous Properties
1327
+   #pragma region Motion Estimation
1328
    m_VideoEncoder->SetHalfPixelMotionEstimationEnabled(!!(obs_data_get_int(data, AMF_H264_MOTIONESTIMATION) & 1));
1329
    m_VideoEncoder->SetQuarterPixelMotionEstimationEnabled(!!(obs_data_get_int(data, AMF_H264_MOTIONESTIMATION) & 2));
1330
+   #pragma endregion Motion Estimation
1331
+
1332
+   #pragma region Experimental
1333
+   try { m_VideoEncoder->SetCodingType((VCECodingType)obs_data_get_int(data, AMF_H264_CODINGTYPE)); } catch (std::exception e) {} catch (...) {}
1334
+   try { m_VideoEncoder->SetWaitForTaskEnabled(!!obs_data_get_int(data, AMF_H264_WAITFORTASK)); } catch (std::exception e) {} catch (...) {}
1335
+   try { m_VideoEncoder->SetPreAnalysisPassEnabled(!!obs_data_get_int(data, AMF_H264_PREANALYSISPASS)); } catch (std::exception e) {} catch (...) {}
1336
+   try { m_VideoEncoder->SetVBAQEnabled(!!obs_data_get_int(data, AMF_H264_VBAQ)); } catch (std::exception e) {} catch (...) {}
1337
+
1338
+   try { m_VideoEncoder->SetHeaderInsertionSpacing((uint32_t)obs_data_get_int(data, AMF_H264_HEADER_INSERTION_SPACING)); } catch (std::exception e) {} catch (...) {}
1339
+   try { m_VideoEncoder->SetMaximumAccessUnitSize((uint32_t)obs_data_get_int(data, AMF_H264_MAXIMUMACCESSUNITSIZE)); } catch (std::exception e) {} catch (...) {}
1340
+   try { m_VideoEncoder->SetMaximumReferenceFrames((uint32_t)obs_data_get_int(data, AMF_H264_MAXIMUMREFERENCEFRAMES)); } catch (std::exception e) {} catch (...) {}
1341
+
1342
+   try { m_VideoEncoder->SetGOPSize((uint32_t)obs_data_get_int(data, AMF_H264_GOPSIZE)); } catch (std::exception e) {} catch (...) {}
1343
+   try { m_VideoEncoder->SetGOPAlignmentEnabled(!!obs_data_get_int(data, AMF_H264_GOPALIGNMENT)); } catch (std::exception e) {} catch (...) {}
1344
+
1345
+   try { m_VideoEncoder->SetIntraRefreshNumberOfStripes((uint32_t)obs_data_get_int(data, AMF_H264_INTRAREFRESH_NUMBEROFSTRIPES)); } catch (std::exception e) {} catch (...) {}
1346
+   try { m_VideoEncoder->SetIntraRefreshMacroblocksPerSlot((uint32_t)obs_data_get_int(data, AMF_H264_INTRAREFRESH_MACROBLOCKSPERSLOT)); } catch (std::exception e) {} catch (...) {}
1347
+
1348
+   try { m_VideoEncoder->SetSlicesPerFrame((uint32_t)obs_data_get_int(data, AMF_H264_SLICESPERFRAME)); } catch (std::exception e) {} catch (...) {}
1349
+   try { m_VideoEncoder->SetSliceMode((VCESliceMode)obs_data_get_int(data, AMF_H264_SLICEMODE)); } catch (std::exception e) {} catch (...) {}
1350
+   try { m_VideoEncoder->SetMaximumSliceSize((uint32_t)obs_data_get_int(data, AMF_H264_MAXIMUMSLICESIZE)); } catch (std::exception e) {} catch (...) {}
1351
+   try { m_VideoEncoder->SetSliceControlMode((VCESliceControlMode)obs_data_get_int(data, AMF_H264_SLICECONTROLMODE)); } catch (std::exception e) {} catch (...) {}
1352
+   try { m_VideoEncoder->SetSliceControlSize((uint32_t)obs_data_get_int(data, AMF_H264_SLICECONTROLSIZE)); } catch (std::exception e) {} catch (...) {}
1353
+   #pragma endregion Experimental
1354
 
1355
    if (m_VideoEncoder->IsStarted()) {
1356
        // OBS - Enforce Streaming Service Stuff
1357
@@ -1542,8 +1682,8 @@
1358
 
1359
                obs_data_set_int(data, "bitrate", m_VideoEncoder->GetTargetBitrate() / 1000);
1360
 
1361
-               obs_data_set_int(data, AMF_H264_BITRATE_TARGET, m_VideoEncoder->GetTargetBitrate() / bitrateMultiplier);
1362
-               obs_data_set_int(data, AMF_H264_BITRATE_PEAK, m_VideoEncoder->GetPeakBitrate() / bitrateMultiplier);
1363
+               obs_data_set_int(data, AMF_H264_BITRATE_TARGET, m_VideoEncoder->GetTargetBitrate() / 1000);
1364
+               obs_data_set_int(data, AMF_H264_BITRATE_PEAK, m_VideoEncoder->GetPeakBitrate() / 1000);
1365
            } else {
1366
                obs_data_set_int(data, "bitrate", m_VideoEncoder->GetTargetBitrate() / 1000);
1367
            }
1368
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Source/misc-util.cpp -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/misc-util.cpp Changed
82
 
1
@@ -29,9 +29,9 @@
2
 
3
 // Plugin
4
 #include "plugin.h"
5
-#include "amd-amf.h"
6
-#include "amd-amf-vce.h"
7
-#include "amd-amf-vce-capabilities.h"
8
+#include "amf.h"
9
+#include "amf-capabilities.h"
10
+#include "amf-h264.h"
11
 
12
 //////////////////////////////////////////////////////////////////////////
13
 // Code
14
@@ -82,6 +82,24 @@
15
            return VCEProfileLevel_52;
16
        }
17
 
18
+       #pragma region VCEEncoderType
19
+       inline const char* VCEEncoderTypeAsString(VCEEncoderType type) {
20
+           const char* types[] = {
21
+               "AVC",
22
+               "SVC",
23
+               "HEVC"
24
+           };
25
+           return types[type];
26
+       }
27
+       inline const wchar_t* VCEEncoderTypeAsAMF(VCEEncoderType type) {
28
+           const wchar_t* types[] = {
29
+               AMFVideoEncoderVCE_AVC,
30
+               AMFVideoEncoderVCE_SVC,
31
+               L"AMFVideoEncoderHW_HEVC"
32
+           };
33
+           return types[type];
34
+       }
35
+       #pragma endregion VCEEncoderType
36
        #pragma region VCEMemoryType
37
        inline const char* MemoryTypeAsString(VCEMemoryType memoryType) {
38
            static const char* memoryTypeToString[] = {
39
@@ -218,12 +236,35 @@
40
        #pragma endregion VCERateControlMethod
41
 
42
        inline const char* CodingTypeAsString(VCECodingType type) {
43
-           const char* TypeToString[] = {
44
-               "Default",
45
-               "CABAC",
46
-               "CALV",
47
-           };
48
-           return TypeToString[type];
49
+           switch (type) {
50
+               case VCECodingType_CABAC:
51
+                   return "CABAC";
52
+               case VCECodingType_CALVC:
53
+                   return "CALVC";
54
+               case VCECodingType_Default:
55
+                   return "Default";
56
+           }
57
+           return "MEMORY CORRUPTION";
58
+       }
59
+       inline const char* SliceModeAsString(VCESliceMode mode) {
60
+           switch (mode) {
61
+               case VCESliceMode_Horizontal:
62
+                   return "Horizontal";
63
+               case VCESliceMode_Vertical:
64
+                   return "Vertical";
65
+           }
66
+           return "MEMORY CORRUPTION";
67
+       }
68
+       inline const char* SliceControlModeAsString(VCESliceControlMode mode) {
69
+           switch (mode) {
70
+               case VCESliceControlMode_Off:
71
+                   return "Off";
72
+               case VCESliceControlMode_Macroblock:
73
+                   return "Macroblock";
74
+               case VCESliceControlMode_Macroblock_Row:
75
+                   return "Macroblock Row";
76
+           }
77
+           return "MEMORY CORRUPTION";
78
        }
79
    }
80
 }
81
\ No newline at end of file
82
obs-studio-0.16.6.tar.xz/plugins/enc-amf/Source/plugin.cpp -> obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/plugin.cpp Changed
78
 
1
@@ -32,8 +32,9 @@
2
 
3
 // Plugin
4
 #include "plugin.h"
5
-#include "amd-amf.h"
6
-#include "amd-amf-vce-capabilities.h"
7
+#include "api-base.h"
8
+#include "amf.h"
9
+#include "amf-capabilities.h"
10
 #include "enc-h264.h"
11
 
12
 //////////////////////////////////////////////////////////////////////////
13
@@ -56,25 +57,54 @@
14
 *                   false to indicate failure and unload the module
15
 */
16
 MODULE_EXPORT bool obs_module_load(void) {
17
-   try {
18
-       AMF_LOG_INFO("Version " PLUGIN_VERSION_TEXT);
19
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Loading...");
20
 
21
-       // Load AMF Runtime
22
-       auto instance = Plugin::AMD::AMF::GetInstance();
23
+   // Attempt to load AMF Runtime
24
+   try {
25
+       Plugin::AMD::AMF::GetInstance();
26
+   } catch (std::exception& e) {
27
+       AMF_LOG_ERROR("%s", e.what());
28
+       return true;
29
+   } catch (std::exception* e) {
30
+       AMF_LOG_ERROR("%s", e->what());
31
+       delete e;
32
+       return true;
33
+   } catch (...) {
34
+       AMF_LOG_ERROR("Unknown Exception.");
35
+       return true;
36
+   }
37
 
38
-       // Report AMF Capabilities
39
-       //Plugin::AMD::VCECapabilities::ReportCapabilities();
40
+   // Initialize Graphics APIs
41
+   try {
42
+       Plugin::API::Base::Initialize();
43
+   } catch (std::exception& e) {
44
+       AMF_LOG_ERROR("%s", e.what());
45
+       return true;
46
+   } catch (std::exception* e) {
47
+       AMF_LOG_ERROR("%s", e->what());
48
+       delete e;
49
+       return true;
50
+   } catch (...) {
51
+       AMF_LOG_ERROR("Unknown Exception.");
52
+       return true;
53
+   }
54
 
55
-       // Register Encoders
56
+   // Register Encoder
57
+   try {
58
        Plugin::Interface::H264Interface::encoder_register();
59
    } catch (std::exception& e) {
60
-       AMF_LOG_ERROR("Uncaught Exception: %s", e.what());
61
+       AMF_LOG_ERROR("%s", e.what());
62
+       return true;
63
    } catch (std::exception* e) {
64
-       AMF_LOG_ERROR("Uncaught Exception: %s", e->what());
65
+       AMF_LOG_ERROR("%s", e->what());
66
        delete e;
67
+       return true;
68
    } catch (...) {
69
-       AMF_LOG_ERROR("Uncaught Unknown Exception.");
70
+       AMF_LOG_ERROR("Unknown Exception.");
71
+       return true;
72
    }
73
+
74
+   AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Complete.");
75
    return true;
76
 }
77
 
78
obs-studio-0.16.6.tar.xz/plugins/image-source/data/locale/tr-TR.ini -> obs-studio-0.17.0.tar.xz/plugins/image-source/data/locale/tr-TR.ini Changed
17
 
1
@@ -1,5 +1,14 @@
2
 ImageInput="Görüntü"
3
 File="Görüntü Dosyası"
4
-UnloadWhenNotShowing="Resim gösterilmediğinde bellekten kaldır"
5
+UnloadWhenNotShowing="Görüntü gösterilmediğinde bellekten kaldır"
6
 
7
+SlideShow="Resim Slayt Gösterisi"
8
+SlideShow.TransitionSpeed="Geçiş Hızı (milisaniye)"
9
+SlideShow.SlideTime="Slaytlar Arası Süre (milisaniye)"
10
+SlideShow.Files="Görüntü Dosyaları"
11
+SlideShow.Transition="Geçiş"
12
+SlideShow.Transition.Cut="Cut"
13
+SlideShow.Transition.Fade="Fade"
14
+SlideShow.Transition.Swipe="Swipe"
15
+SlideShow.Transition.Slide="Slide"
16
 
17
obs-studio-0.16.6.tar.xz/plugins/image-source/image-source.c -> obs-studio-0.17.0.tar.xz/plugins/image-source/image-source.c Changed
9
 
1
@@ -151,7 +151,6 @@
2
    if (!context->image.texture)
3
        return;
4
 
5
-   gs_reset_blend_state();
6
    gs_effect_set_texture(gs_effect_get_param_by_name(effect, "image"),
7
            context->image.texture);
8
    gs_draw_sprite(context->image.texture, 0,
9
obs-studio-0.17.0.tar.xz/plugins/linux-alsa/data/locale/vi-VN.ini Added
5
 
1
@@ -0,0 +1,3 @@
2
+AlsaInput="Thiết bị thu âm thanh (ALSA)"
3
+Device="Thiết bị"
4
+
5
obs-studio-0.17.0.tar.xz/plugins/linux-capture/data/locale/vi-VN.ini Added
18
 
1
@@ -0,0 +1,16 @@
2
+X11SharedMemoryScreenInput="Quay màn hỉnh (XSHM)"
3
+Screen="Màn hình"
4
+CaptureCursor="Quay cả con trỏ"
5
+AdvancedSettings="Cài đặt nâng cao"
6
+XServer="X Server"
7
+XCCapture="Quay cửa sổ (Xcomposite)"
8
+Window="Cửa sổ"
9
+CropTop="Cắt bên trên (pixels)"
10
+CropLeft="Cắt bên trái (pixels)"
11
+CropRight="Cắt bên phải (pixels)"
12
+CropBottom="Cắt bên dưới (pixels)"
13
+SwapRedBlue="Đổi đỏ và xanh"
14
+LockX="Khóa X server khi quay"
15
+IncludeXBorder="Bao gồm X Border"
16
+ExcludeAlpha="Dùng texture format không có Alpha (Cách giải quyết với Mesa driver)"
17
+
18
obs-studio-0.16.6.tar.xz/plugins/mac-avcapture/data/locale/tr-TR.ini -> obs-studio-0.17.0.tar.xz/plugins/mac-avcapture/data/locale/tr-TR.ini Changed
9
 
1
@@ -4,6 +4,7 @@
2
 Preset="Ön Tanımlı"
3
 Buffering="Arabelleğe Almayı Kullan"
4
 FrameRate="Kare hızı"
5
+InputFormat="Giriş biçimi"
6
 ColorSpace="Renk alanı"
7
 VideoRange="Video aralığı"
8
 VideoRange.Partial="Kısmi"
9
obs-studio-0.16.6.tar.xz/plugins/mac-capture/data/locale/nl-NL.ini -> obs-studio-0.17.0.tar.xz/plugins/mac-capture/data/locale/nl-NL.ini Changed
9
 
1
@@ -1,5 +1,5 @@
2
-CoreAudio.InputCapture="Audioinvoer Capture"
3
-CoreAudio.OutputCapture="Audiouitvoer Capture"
4
+CoreAudio.InputCapture="Audioinvoer Opname"
5
+CoreAudio.OutputCapture="Audiouitvoer Opname"
6
 CoreAudio.Device="Apparaat"
7
 CoreAudio.Device.Default="Standaardinstellingen"
8
 DisplayCapture="Beeldschermcapture"
9
obs-studio-0.16.6.tar.xz/plugins/mac-vth264/data/locale/tr-TR.ini -> obs-studio-0.17.0.tar.xz/plugins/mac-vth264/data/locale/tr-TR.ini Changed
8
 
1
@@ -1,3 +1,6 @@
2
+VTH264EncHW="Apple VT H264 Donanım Kodlayıcı"
3
+VTH264EncSW="Apple VT H264 Yazılım Kodlayıcı"
4
+VTEncoder="VideoToolbox Kodlayıcı"
5
 Bitrate="Bithızı"
6
 MaxBitrate="Maks bit hızı"
7
 KeyframeIntervalSec="Anahtarkare Aralığı (saniye, 0=otomatik)"
8
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/ar-SA.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/ar-SA.ini Changed
14
 
1
@@ -3,6 +3,7 @@
2
 Bitrate="معدل النقل"
3
 Preset="الإعداد المسبق"
4
 
5
+
6
 NVENC.Preset.default="الإفتراضي"
7
 NVENC.Preset.hq="جودة عالية"
8
 NVENC.Preset.hp="أداء عالي"
9
@@ -25,3 +26,4 @@
10
 MediaFileFilter.AudioFiles="ملفات الصوت"
11
 MediaFileFilter.AllFiles="‮كل الملفات"
12
 
13
+
14
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/bg-BG.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/bg-BG.ini Changed
7
 
1
@@ -5,3 +5,5 @@
2
 
3
 
4
 
5
+
6
+
7
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/ca-ES.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/ca-ES.ini Changed
14
 
1
@@ -6,6 +6,7 @@
2
 KeyframeIntervalSec="Interval de fotograma clau (en segons, 0 = automàtic)"
3
 Lossless="Sense pèrdues"
4
 
5
+
6
 NVENC.Use2Pass="Utilitza codificació en dues passades"
7
 NVENC.Preset.default="Per defecte"
8
 NVENC.Preset.hq="Alta Qualitat"
9
@@ -47,3 +48,4 @@
10
 MediaFileFilter.AudioFiles="Arxius d'àudio"
11
 MediaFileFilter.AllFiles="Tots els fitxers"
12
 
13
+
14
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/cs-CZ.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/cs-CZ.ini Changed
16
 
1
@@ -6,6 +6,7 @@
2
 KeyframeIntervalSec="Interval klíč. snímků (vteřiny, 0=auto)"
3
 Lossless="Lossless"
4
 
5
+
6
 NVENC.Use2Pass="Použít dvoustupňové enkódování"
7
 NVENC.Preset.default="Výchozí"
8
 NVENC.Preset.hq="Vysoká kvalita"
9
@@ -47,3 +48,6 @@
10
 MediaFileFilter.AudioFiles="Zvukové soubory"
11
 MediaFileFilter.AllFiles="Všechny soubory"
12
 
13
+ReplayBuffer="Záznam do paměti"
14
+ReplayBuffer.Save="Uložit záznam"
15
+
16
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/da-DK.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/da-DK.ini Changed
17
 
1
@@ -6,6 +6,8 @@
2
 KeyframeIntervalSec="Keyframe-interval (sekunder, 0= auto)"
3
 Lossless="Tabsfri"
4
 
5
+BFrames="B-rammer"
6
+
7
 NVENC.Use2Pass="Benyt to-trins kodning"
8
 NVENC.Preset.default="Standard"
9
 NVENC.Preset.hq="Høj kvalitet"
10
@@ -47,3 +49,6 @@
11
 MediaFileFilter.AudioFiles="Lydfiler"
12
 MediaFileFilter.AllFiles="Alle filer"
13
 
14
+ReplayBuffer="Genafspilningsbuffer"
15
+ReplayBuffer.Save="Gem Genafspilning"
16
+
17
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/de-DE.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/de-DE.ini Changed
17
 
1
@@ -6,6 +6,8 @@
2
 KeyframeIntervalSec="Keyframeintervall (Sekunden, 0=auto)"
3
 Lossless="Verlustfrei"
4
 
5
+BFrames="B-frames"
6
+
7
 NVENC.Use2Pass="Benutze Two-Pass Encoding"
8
 NVENC.Preset.default="Standard"
9
 NVENC.Preset.hq="Hohe Qualität"
10
@@ -47,3 +49,6 @@
11
 MediaFileFilter.AudioFiles="Audio-Dateien"
12
 MediaFileFilter.AllFiles="Alle Dateien"
13
 
14
+ReplayBuffer="Replaypuffer"
15
+ReplayBuffer.Save="Replay speichern"
16
+
17
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/el-GR.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/el-GR.ini Changed
14
 
1
@@ -2,6 +2,7 @@
2
 FFmpegAAC="FFmpeg προεπιλεγμένος κωδικοποιητής AAC"
3
 Bitrate="Ρυθμός μετάδοσης bit"
4
 
5
+
6
 NVENC.Preset.default="Προεπιλογή"
7
 
8
 LocalFile="Τοπικό αρχείο"
9
@@ -19,3 +20,4 @@
10
 
11
 
12
 
13
+
14
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/en-US.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/en-US.ini Changed
8
 
1
@@ -48,3 +48,6 @@
2
 MediaFileFilter.VideoFiles="Video Files"
3
 MediaFileFilter.AudioFiles="Audio Files"
4
 MediaFileFilter.AllFiles="All Files"
5
+
6
+ReplayBuffer="Replay Buffer"
7
+ReplayBuffer.Save="Save Replay"
8
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/es-ES.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/es-ES.ini Changed
17
 
1
@@ -6,6 +6,8 @@
2
 KeyframeIntervalSec="Intervalo de keyframes (segundos, 0=auto)"
3
 Lossless="Sin pérdidas"
4
 
5
+BFrames="B-Frames"
6
+
7
 NVENC.Use2Pass="Usar codificación en dos pasadas"
8
 NVENC.Preset.default="Por defecto"
9
 NVENC.Preset.hq="Alta Calidad"
10
@@ -47,3 +49,6 @@
11
 MediaFileFilter.AudioFiles="Archivos de audio"
12
 MediaFileFilter.AllFiles="Todos los Archivos"
13
 
14
+ReplayBuffer="Búfer de reproducción"
15
+ReplayBuffer.Save="Guardar repetición"
16
+
17
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/eu-ES.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/eu-ES.ini Changed
17
 
1
@@ -6,6 +6,8 @@
2
 KeyframeIntervalSec="Gako-fotogramen tartea (segundoak, 0=auto)"
3
 Lossless="Galerarik gabe"
4
 
5
+BFrames="B-fotogramak"
6
+
7
 NVENC.Use2Pass="Erabili bi urratseko kodeketa"
8
 NVENC.Preset.default="Lehenetsia"
9
 NVENC.Preset.hq="Kalitate handia"
10
@@ -47,3 +49,6 @@
11
 MediaFileFilter.AudioFiles="Audio-fitxategiak"
12
 MediaFileFilter.AllFiles="Fitxategi guztiak"
13
 
14
+ReplayBuffer="Erreprodukzio bufferra"
15
+ReplayBuffer.Save="Gorde erreprodukzioa"
16
+
17
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/fi-FI.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/fi-FI.ini Changed
17
 
1
@@ -6,6 +6,8 @@
2
 KeyframeIntervalSec="Keyframe-väli (sekunteina, 0=automaattinen)"
3
 Lossless="Häviötön"
4
 
5
+BFrames="B-kehykset"
6
+
7
 NVENC.Use2Pass="Käytä Two-Pass enkoodausta"
8
 NVENC.Preset.default="Oletusarvo"
9
 NVENC.Preset.hq="Korkea laatu"
10
@@ -47,3 +49,6 @@
11
 MediaFileFilter.AudioFiles="Äänitiedostot"
12
 MediaFileFilter.AllFiles="Kaikki tiedostot"
13
 
14
+ReplayBuffer="Toistopuskuri"
15
+ReplayBuffer.Save="Tallenna uusinta"
16
+
17
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/fr-FR.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/fr-FR.ini Changed
17
 
1
@@ -6,6 +6,8 @@
2
 KeyframeIntervalSec="Intervalle d'image-clé (en secondes, 0 = auto)"
3
 Lossless="Sans perte"
4
 
5
+BFrames="B-frames"
6
+
7
 NVENC.Use2Pass="Utiliser l'encodage double passe"
8
 NVENC.Preset.default="Défaut"
9
 NVENC.Preset.hq="Haute qualité"
10
@@ -47,3 +49,6 @@
11
 MediaFileFilter.AudioFiles="Fichiers audio"
12
 MediaFileFilter.AllFiles="Tous les fichiers"
13
 
14
+ReplayBuffer="Tampon de relecture"
15
+ReplayBuffer.Save="Sauvegarder la relecture"
16
+
17
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/gl-ES.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/gl-ES.ini Changed
14
 
1
@@ -2,6 +2,7 @@
2
 FFmpegAAC="Codificador AAC FFmpeg predefinido"
3
 Bitrate="Velocidade de bits"
4
 
5
+
6
 NVENC.Level="Nivel"
7
 
8
 FFmpegSource="Fonte multimedia"
9
@@ -24,3 +25,4 @@
10
 
11
 
12
 
13
+
14
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/he-IL.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/he-IL.ini Changed
14
 
1
@@ -6,6 +6,7 @@
2
 KeyframeIntervalSec="מרווח ערך ה keyframe בשניות (0=אוטומטי)"
3
 Lossless="ללא אובדן נתונים"
4
 
5
+
6
 NVENC.Use2Pass="השתמש בקידוד שני מעברים"
7
 NVENC.Preset.default="ברירת מחדל"
8
 NVENC.Preset.hq="איכות גבוהה"
9
@@ -47,3 +48,4 @@
10
 MediaFileFilter.AudioFiles="קבצי אודיו"
11
 MediaFileFilter.AllFiles="כל הקבצים"
12
 
13
+
14
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/hr-HR.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/hr-HR.ini Changed
14
 
1
@@ -6,6 +6,7 @@
2
 KeyframeIntervalSec="Interval ključnih frejmova (sekunde, 0=automatski)"
3
 Lossless="Bez gubitka"
4
 
5
+
6
 NVENC.Use2Pass="Koristi enkoding duplog prolaza"
7
 NVENC.Preset.default="Podrazumevani"
8
 NVENC.Preset.hq="Visoki kvalitet"
9
@@ -47,3 +48,4 @@
10
 MediaFileFilter.AudioFiles="Zvučne datoteke"
11
 MediaFileFilter.AllFiles="Sve datoteke"
12
 
13
+
14
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/hu-HU.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/hu-HU.ini Changed
17
 
1
@@ -6,6 +6,8 @@
2
 KeyframeIntervalSec="Kulcsképkocka időköze (másodperc, 0=auto)"
3
 Lossless="Veszteségmentes"
4
 
5
+BFrames="B képkocka"
6
+
7
 NVENC.Use2Pass="Kétmenetes kódolás"
8
 NVENC.Preset.default="Alapértelmezett"
9
 NVENC.Preset.hq="Kiváló minőség"
10
@@ -47,3 +49,6 @@
11
 MediaFileFilter.AudioFiles="Hangfájlok"
12
 MediaFileFilter.AllFiles="Minden fájl"
13
 
14
+ReplayBuffer="Visszajátszás puffer"
15
+ReplayBuffer.Save="Visszajátszás mentése"
16
+
17
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/it-IT.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/it-IT.ini Changed
14
 
1
@@ -6,6 +6,7 @@
2
 KeyframeIntervalSec="Intervallo Keyframe (secondi, 0=automatico)"
3
 Lossless="Lossless"
4
 
5
+
6
 NVENC.Use2Pass="Usa codifica in due passaggi"
7
 NVENC.Preset.default="Predefinito"
8
 NVENC.Preset.hq="Alta Qualità"
9
@@ -47,3 +48,4 @@
10
 MediaFileFilter.AudioFiles="File audio"
11
 MediaFileFilter.AllFiles="Tutti i file"
12
 
13
+
14
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/ja-JP.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/ja-JP.ini Changed
17
 
1
@@ -6,6 +6,8 @@
2
 KeyframeIntervalSec="キーフレーム間隔 (秒, 0=自動)"
3
 Lossless="無損失"
4
 
5
+BFrames="B-フレーム"
6
+
7
 NVENC.Use2Pass="2パスエンコードを使用"
8
 NVENC.Preset.default="既定"
9
 NVENC.Preset.hq="高品質"
10
@@ -47,3 +49,6 @@
11
 MediaFileFilter.AudioFiles="オーディオファイル"
12
 MediaFileFilter.AllFiles="すべてのファイル"
13
 
14
+ReplayBuffer="リプレイバッファー"
15
+ReplayBuffer.Save="リプレイ保存"
16
+
17
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/ko-KR.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/ko-KR.ini Changed
17
 
1
@@ -6,6 +6,8 @@
2
 KeyframeIntervalSec="키프레임 간격 (초 단위, 0=자동)"
3
 Lossless="무손실"
4
 
5
+BFrames="B-화면"
6
+
7
 NVENC.Use2Pass="2 패스 인코딩 사용"
8
 NVENC.Preset.default="기본"
9
 NVENC.Preset.hq="우수한 품질"
10
@@ -47,3 +49,6 @@
11
 MediaFileFilter.AudioFiles="오디오 파일"
12
 MediaFileFilter.AllFiles="모든 파일"
13
 
14
+ReplayBuffer="리플레이 버퍼"
15
+ReplayBuffer.Save="리플레이 저장"
16
+
17
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/nb-NO.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/nb-NO.ini Changed
14
 
1
@@ -6,6 +6,7 @@
2
 KeyframeIntervalSec="Nøkkelbildeintervall (sekunder, 0 = automatisk)"
3
 Lossless="Tapsfri"
4
 
5
+
6
 NVENC.Use2Pass="Bruk tostegskoding"
7
 NVENC.Preset.default="Standard"
8
 NVENC.Preset.hq="Høy kvalitet"
9
@@ -47,3 +48,4 @@
10
 MediaFileFilter.AudioFiles="Lydfiler"
11
 MediaFileFilter.AllFiles="Alle filer"
12
 
13
+
14
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/nl-NL.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/nl-NL.ini Changed
17
 
1
@@ -6,6 +6,8 @@
2
 KeyframeIntervalSec="Tijd tussen keyframes (seconden, 0=auto)"
3
 Lossless="Lossless"
4
 
5
+BFrames="B-frames"
6
+
7
 NVENC.Use2Pass="Gebruik two-pass encoding"
8
 NVENC.Preset.default="Standaard"
9
 NVENC.Preset.hq="Hoge kwaliteit"
10
@@ -47,3 +49,6 @@
11
 MediaFileFilter.AudioFiles="Audiobestanden"
12
 MediaFileFilter.AllFiles="Alle bestanden"
13
 
14
+ReplayBuffer="Replay Buffer"
15
+ReplayBuffer.Save="Replay Opslaan"
16
+
17
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/pl-PL.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/pl-PL.ini Changed
17
 
1
@@ -6,6 +6,8 @@
2
 KeyframeIntervalSec="Odstęp między klatkami kluczowymi (sekundy, 0=automatyczny)"
3
 Lossless="Bezstratny"
4
 
5
+BFrames="B-ramki"
6
+
7
 NVENC.Use2Pass="Użyj enkodowania dwuprzebiegowego"
8
 NVENC.Preset.default="Domyślny"
9
 NVENC.Preset.hq="Wysoka jakość"
10
@@ -47,3 +49,6 @@
11
 MediaFileFilter.AudioFiles="Pliki audio"
12
 MediaFileFilter.AllFiles="Wszystkie pliki"
13
 
14
+ReplayBuffer="Bufor replay"
15
+ReplayBuffer.Save="Zapisz replay"
16
+
17
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/pt-BR.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/pt-BR.ini Changed
14
 
1
@@ -6,6 +6,7 @@
2
 KeyframeIntervalSec="Intervalo de Keyframe (segundos, 0=auto)"
3
 Lossless="Sem perdas"
4
 
5
+
6
 NVENC.Use2Pass="Utilizar a codificação em dois passos"
7
 NVENC.Preset.default="Padrão"
8
 NVENC.Preset.hq="Alta Qualidade"
9
@@ -47,3 +48,4 @@
10
 MediaFileFilter.AudioFiles="Arquivos de Áudio"
11
 MediaFileFilter.AllFiles="Todos os Arquivos"
12
 
13
+
14
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/pt-PT.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/pt-PT.ini Changed
14
 
1
@@ -6,6 +6,7 @@
2
 KeyframeIntervalSec="Intervalo do keyframe (segundos, 0=automático)"
3
 Lossless="Sem perdas"
4
 
5
+
6
 NVENC.Preset.default="Predefinido"
7
 NVENC.Preset.hq="Alta Qualidade"
8
 NVENC.Preset.hp="Alto Desempenho"
9
@@ -46,3 +47,4 @@
10
 MediaFileFilter.AudioFiles="Arquivos de Áudio"
11
 MediaFileFilter.AllFiles="Todos os ficheiros"
12
 
13
+
14
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/ro-RO.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/ro-RO.ini Changed
14
 
1
@@ -3,6 +3,7 @@
2
 Bitrate="Rată de biți"
3
 Preset="Presetare"
4
 
5
+
6
 NVENC.Preset.default="Implicită"
7
 NVENC.Preset.bd="Bluray"
8
 NVENC.Level="Nivel"
9
@@ -38,3 +39,4 @@
10
 MediaFileFilter.AudioFiles="Fișiere audio"
11
 MediaFileFilter.AllFiles="Toate fișierele"
12
 
13
+
14
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/ru-RU.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/ru-RU.ini Changed
15
 
1
@@ -6,6 +6,7 @@
2
 KeyframeIntervalSec="Интервал ключевых кадров (сек, 0=авто)"
3
 Lossless="Без потерь"
4
 
5
+
6
 NVENC.Use2Pass="Использовать двухпроходное кодирование"
7
 NVENC.Preset.default="По умолчанию"
8
 NVENC.Preset.hq="Высокое качество"
9
@@ -47,3 +48,5 @@
10
 MediaFileFilter.AudioFiles="Аудиофайлы"
11
 MediaFileFilter.AllFiles="Все файлы"
12
 
13
+ReplayBuffer.Save="Сохранить повтор"
14
+
15
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/sk-SK.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/sk-SK.ini Changed
13
 
1
@@ -3,9 +3,11 @@
2
 Bitrate="Bitrate"
3
 
4
 
5
+
6
 Looping="Slučka"
7
 Advanced="Rozšírené"
8
 DiscardNone="Žiadny"
9
 
10
 
11
 
12
+
13
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/sl-SI.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/sl-SI.ini Changed
14
 
1
@@ -3,6 +3,7 @@
2
 Bitrate="Bitrate"
3
 
4
 
5
+
6
 FFmpegSource="Medijski Vir"
7
 LocalFile="Lokalna Datoteka"
8
 Looping="Ponavljaj"
9
@@ -25,3 +26,4 @@
10
 
11
 
12
 
13
+
14
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/sr-CS.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/sr-CS.ini Changed
14
 
1
@@ -6,6 +6,7 @@
2
 KeyframeIntervalSec="Interval ključnih frejmova (sekunde, 0=automatski)"
3
 Lossless="Bez gubitka"
4
 
5
+
6
 NVENC.Use2Pass="Koristi enkoding duplog prolaza"
7
 NVENC.Preset.default="Podrazumevani"
8
 NVENC.Preset.hq="Visoki kvalitet"
9
@@ -47,3 +48,4 @@
10
 MediaFileFilter.AudioFiles="Zvučne datoteke"
11
 MediaFileFilter.AllFiles="Sve datoteke"
12
 
13
+
14
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/sr-SP.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/sr-SP.ini Changed
14
 
1
@@ -6,6 +6,7 @@
2
 KeyframeIntervalSec="Интервал кључних фрејмова (секунде, 0=аутоматски)"
3
 Lossless="Без губитка"
4
 
5
+
6
 NVENC.Use2Pass="Користи енкодинг дуплог пролаза"
7
 NVENC.Preset.default="Подразумевани"
8
 NVENC.Preset.hq="Високи квалитет"
9
@@ -47,3 +48,4 @@
10
 MediaFileFilter.AudioFiles="Звучне датотеке"
11
 MediaFileFilter.AllFiles="Све датотеке"
12
 
13
+
14
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/sv-SE.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/sv-SE.ini Changed
14
 
1
@@ -6,6 +6,7 @@
2
 KeyframeIntervalSec="Intervall för keyframes (sekunder, 0=automatisk)"
3
 Lossless="Förlustfri"
4
 
5
+
6
 NVENC.Use2Pass="Använd tvåpassavkodning"
7
 NVENC.Preset.default="Standard"
8
 NVENC.Preset.hq="Hög kvalitet"
9
@@ -47,3 +48,4 @@
10
 MediaFileFilter.AudioFiles="Ljudfiler"
11
 MediaFileFilter.AllFiles="Alla filer"
12
 
13
+
14
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/th-TH.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/th-TH.ini Changed
7
 
1
@@ -4,3 +4,5 @@
2
 
3
 
4
 
5
+
6
+
7
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/tr-TR.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/tr-TR.ini Changed
36
 
1
@@ -3,10 +3,17 @@
2
 Bitrate="Bit hızı"
3
 Preset="Ön Tanımlı"
4
 KeyframeIntervalSec="Anahtarkare Aralığı (saniye, 0=otomatik)"
5
+Lossless="Kayıpsız"
6
+
7
 
8
 NVENC.Preset.default="Varsayılan"
9
 NVENC.Preset.hq="Yüksek Kalite"
10
 NVENC.Preset.hp="Yüksek Performans"
11
+NVENC.Preset.bd="Bluray"
12
+NVENC.Preset.ll="Düşük Gecikme"
13
+NVENC.Preset.llhq="Düşük Gecikme Yüksek Kalite"
14
+NVENC.Preset.llhp="Düşük Gecikme Yüksek Performans"
15
+NVENC.Level="Seviye"
16
 
17
 FFmpegSource="Ortam Kaynağı"
18
 LocalFile="Yerel Dosya"
19
@@ -27,6 +34,10 @@
20
 DiscardNonIntra="Intra Olmayan Kareler"
21
 DiscardNonKey="Anahtar Olmayan Kareler"
22
 DiscardAll="Tüm Kareler (Dikkatli Olun!)"
23
+ColorRange="YUV Renk Aralığı"
24
+ColorRange.Auto="Otomatik"
25
+ColorRange.Partial="Kısmi"
26
+ColorRange.Full="Tam"
27
 
28
 
29
 MediaFileFilter.AllMediaFiles="Tüm Medya Dosyaları"
30
@@ -34,3 +45,5 @@
31
 MediaFileFilter.AudioFiles="Ses Dosyaları"
32
 MediaFileFilter.AllFiles="Tüm Dosyalar"
33
 
34
+ReplayBuffer="Tekrar Oynatma Arabelleği"
35
+
36
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/uk-UA.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/uk-UA.ini Changed
17
 
1
@@ -6,6 +6,8 @@
2
 KeyframeIntervalSec="Інтервал ключових кадрів (секунд, 0 = авто)"
3
 Lossless="Без втрат"
4
 
5
+BFrames="B-кадри"
6
+
7
 NVENC.Use2Pass="Використовувати двопрохідне кодування"
8
 NVENC.Preset.default="Стандартний"
9
 NVENC.Preset.hq="Висока якість"
10
@@ -47,3 +49,6 @@
11
 MediaFileFilter.AudioFiles="Аудіо"
12
 MediaFileFilter.AllFiles="Всі файли"
13
 
14
+ReplayBuffer="Запис Повторів"
15
+ReplayBuffer.Save="Зберегти Повтор"
16
+
17
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/vi-VN.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/vi-VN.ini Changed
14
 
1
@@ -6,6 +6,7 @@
2
 KeyframeIntervalSec="Thời gian đặt Keyframe (giây, 0=tự động)"
3
 Lossless="Lossless"
4
 
5
+
6
 NVENC.Use2Pass="Sử dụng 2-Pass Encoding"
7
 NVENC.Preset.default="Mặc định"
8
 NVENC.Preset.hq="Chất lượng cao"
9
@@ -23,3 +24,4 @@
10
 
11
 
12
 
13
+
14
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/zh-CN.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/zh-CN.ini Changed
17
 
1
@@ -6,6 +6,8 @@
2
 KeyframeIntervalSec="关键帧间隔(秒, 0=自动)"
3
 Lossless="无损"
4
 
5
+BFrames="B 帧"
6
+
7
 NVENC.Use2Pass="使用 Two-Pass 编码"
8
 NVENC.Preset.default="默认"
9
 NVENC.Preset.hq="高质量"
10
@@ -47,3 +49,6 @@
11
 MediaFileFilter.AudioFiles="音频文件"
12
 MediaFileFilter.AllFiles="所有文件"
13
 
14
+ReplayBuffer="回放缓存"
15
+ReplayBuffer.Save="保存回放"
16
+
17
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/data/locale/zh-TW.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/zh-TW.ini Changed
17
 
1
@@ -6,6 +6,8 @@
2
 KeyframeIntervalSec="關鍵訊框間隔 (秒,0 = 自動)"
3
 Lossless="無損"
4
 
5
+BFrames="B 訊框"
6
+
7
 NVENC.Use2Pass="使用 Two-Pass 編碼"
8
 NVENC.Preset.default="預設"
9
 NVENC.Preset.hq="高品質"
10
@@ -47,3 +49,6 @@
11
 MediaFileFilter.AudioFiles="音效檔"
12
 MediaFileFilter.AllFiles="所有檔案"
13
 
14
+ReplayBuffer="重播緩衝"
15
+ReplayBuffer.Save="儲存重播"
16
+
17
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-aac.c -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-aac.c Changed
10
 
1
@@ -259,7 +259,7 @@
2
    obs_properties_t *props = obs_properties_create();
3
 
4
    obs_properties_add_int(props, "bitrate",
5
-           obs_module_text("Bitrate"), 32, 320, 32);
6
+           obs_module_text("Bitrate"), 64, 320, 32);
7
    return props;
8
 }
9
 
10
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-mux.c -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-mux.c Changed
462
 
1
@@ -16,9 +16,13 @@
2
 ******************************************************************************/
3
 
4
 #include <obs-module.h>
5
+#include <obs-hotkey.h>
6
 #include <obs-avc.h>
7
 #include <util/dstr.h>
8
 #include <util/pipe.h>
9
+#include <util/darray.h>
10
+#include <util/platform.h>
11
+#include <util/circlebuf.h>
12
 #include <util/threading.h>
13
 #include "ffmpeg-mux/ffmpeg-mux.h"
14
 
15
@@ -40,17 +44,55 @@
16
    volatile bool     active;
17
    volatile bool     stopping;
18
    volatile bool     capturing;
19
+
20
+   /* replay buffer */
21
+   struct circlebuf  packets;
22
+   int64_t           cur_size;
23
+   int64_t           cur_time;
24
+   int64_t           max_size;
25
+   int64_t           max_time;
26
+   int64_t           save_ts;
27
+   int               keyframes;
28
+   obs_hotkey_id     hotkey;
29
+
30
+   DARRAY(struct encoder_packet) mux_packets;
31
+   pthread_t                     mux_thread;
32
+   bool                          mux_thread_joinable;
33
+   volatile bool                 muxing;
34
 };
35
 
36
-static const char *ffmpeg_mux_getname(void *unused)
37
+static const char *ffmpeg_mux_getname(void *type)
38
 {
39
-   UNUSED_PARAMETER(unused);
40
+   UNUSED_PARAMETER(type);
41
    return obs_module_text("FFmpegMuxer");
42
 }
43
 
44
+static inline void replay_buffer_clear(struct ffmpeg_muxer *stream)
45
+{
46
+   while (stream->packets.size > 0) {
47
+       struct encoder_packet pkt;
48
+       circlebuf_pop_front(&stream->packets, &pkt, sizeof(pkt));
49
+       obs_encoder_packet_release(&pkt);
50
+   }
51
+
52
+   circlebuf_free(&stream->packets);
53
+   stream->cur_size = 0;
54
+   stream->cur_time = 0;
55
+   stream->max_size = 0;
56
+   stream->max_time = 0;
57
+   stream->save_ts = 0;
58
+   stream->keyframes = 0;
59
+}
60
+
61
 static void ffmpeg_mux_destroy(void *data)
62
 {
63
    struct ffmpeg_muxer *stream = data;
64
+
65
+   replay_buffer_clear(stream);
66
+   if (stream->mux_thread_joinable)
67
+       pthread_join(stream->mux_thread, NULL);
68
+   da_free(stream->mux_packets);
69
+
70
    os_process_pipe_destroy(stream->pipe);
71
    dstr_free(&stream->path);
72
    bfree(stream);
73
@@ -177,7 +219,8 @@
74
    dstr_free(&mux);
75
 }
76
 
77
-static void build_command_line(struct ffmpeg_muxer *stream, struct dstr *cmd)
78
+static void build_command_line(struct ffmpeg_muxer *stream, struct dstr *cmd,
79
+       const char *path)
80
 {
81
    obs_encoder_t *vencoder = obs_output_get_video_encoder(stream->output);
82
    obs_encoder_t *aencoders[MAX_AUDIO_MIXES];
83
@@ -196,7 +239,11 @@
84
    dstr_init_move_array(cmd, obs_module_file(FFMPEG_MUX));
85
    dstr_insert_ch(cmd, 0, '\"');
86
    dstr_cat(cmd, "\" \"");
87
+
88
+   dstr_copy(&stream->path, path);
89
+   dstr_replace(&stream->path, "\"", "\"\"");
90
    dstr_cat_dstr(cmd, &stream->path);
91
+
92
    dstr_catf(cmd, "\" %d %d ", vencoder ? 1 : 0, num_tracks);
93
 
94
    if (vencoder)
95
@@ -213,11 +260,18 @@
96
    add_muxer_params(cmd, stream);
97
 }
98
 
99
+static inline void start_pipe(struct ffmpeg_muxer *stream, const char *path)
100
+{
101
+   struct dstr cmd;
102
+   build_command_line(stream, &cmd, path);
103
+   stream->pipe = os_process_pipe_create(cmd.array, "w");
104
+   dstr_free(&cmd);
105
+}
106
+
107
 static bool ffmpeg_mux_start(void *data)
108
 {
109
    struct ffmpeg_muxer *stream = data;
110
    obs_data_t *settings;
111
-   struct dstr cmd;
112
    const char *path;
113
 
114
    if (!obs_output_can_begin_data_capture(stream->output, 0))
115
@@ -227,14 +281,9 @@
116
 
117
    settings = obs_output_get_settings(stream->output);
118
    path = obs_data_get_string(settings, "path");
119
-   dstr_copy(&stream->path, path);
120
-   dstr_replace(&stream->path, "\"", "\"\"");
121
+   start_pipe(stream, path);
122
    obs_data_release(settings);
123
 
124
-   build_command_line(stream, &cmd);
125
-   stream->pipe = os_process_pipe_create(cmd.array, "w");
126
-   dstr_free(&cmd);
127
-
128
    if (!stream->pipe) {
129
        warn("Failed to create process pipe");
130
        return false;
131
@@ -424,3 +473,330 @@
132
    .encoded_packet = ffmpeg_mux_data,
133
    .get_properties = ffmpeg_mux_properties
134
 };
135
+
136
+/* ------------------------------------------------------------------------ */
137
+
138
+static const char *replay_buffer_getname(void *type)
139
+{
140
+   UNUSED_PARAMETER(type);
141
+   return obs_module_text("ReplayBuffer");
142
+}
143
+
144
+static bool replay_buffer_hotkey(void *data, obs_hotkey_id id,
145
+       obs_hotkey_t *hotkey, bool pressed)
146
+{
147
+   struct ffmpeg_muxer *stream = data;
148
+   if (os_atomic_load_bool(&stream->active))
149
+       stream->save_ts = os_gettime_ns() / 1000LL;
150
+   return true;
151
+}
152
+
153
+static void *replay_buffer_create(obs_data_t *settings, obs_output_t *output)
154
+{
155
+   struct ffmpeg_muxer *stream = bzalloc(sizeof(*stream));
156
+   stream->output = output;
157
+
158
+   stream->hotkey = obs_hotkey_register_output(output,
159
+           "ReplayBuffer.Save",
160
+           obs_module_text("ReplayBuffer.Save"),
161
+           replay_buffer_hotkey, stream);
162
+
163
+   UNUSED_PARAMETER(settings);
164
+   return stream;
165
+}
166
+
167
+static void replay_buffer_destroy(void *data)
168
+{
169
+   struct ffmpeg_muxer *stream = data;
170
+   if (stream->hotkey)
171
+       obs_hotkey_unregister(stream->hotkey);
172
+   ffmpeg_mux_destroy(data);
173
+}
174
+
175
+static bool replay_buffer_start(void *data)
176
+{
177
+   struct ffmpeg_muxer *stream = data;
178
+
179
+   if (!obs_output_can_begin_data_capture(stream->output, 0))
180
+       return false;
181
+   if (!obs_output_initialize_encoders(stream->output, 0))
182
+       return false;
183
+
184
+   obs_data_t *s = obs_output_get_settings(stream->output);
185
+   stream->max_time = obs_data_get_int(s, "max_time_sec") * 1000000LL;
186
+   stream->max_size = obs_data_get_int(s, "max_size_mb") * (1024 * 1024);
187
+   obs_data_release(s);
188
+
189
+   os_atomic_set_bool(&stream->active, true);
190
+   os_atomic_set_bool(&stream->capturing, true);
191
+   obs_output_begin_data_capture(stream->output, 0);
192
+
193
+   return true;
194
+}
195
+
196
+static bool purge_front(struct ffmpeg_muxer *stream)
197
+{
198
+   struct encoder_packet pkt;
199
+   bool keyframe;
200
+
201
+   circlebuf_pop_front(&stream->packets, &pkt, sizeof(pkt));
202
+
203
+   keyframe = pkt.type == OBS_ENCODER_VIDEO && pkt.keyframe;
204
+
205
+   if (keyframe)
206
+       stream->keyframes--;
207
+
208
+   if (!stream->packets.size) {
209
+       stream->cur_size = 0;
210
+       stream->cur_time = 0;
211
+   } else {
212
+       struct encoder_packet first;
213
+       circlebuf_peek_front(&stream->packets, &first, sizeof(first));
214
+       stream->cur_time = first.dts_usec;
215
+       stream->cur_size -= (int64_t)pkt.size;
216
+   }
217
+
218
+   obs_encoder_packet_release(&pkt);
219
+   return keyframe;
220
+}
221
+
222
+static inline void purge(struct ffmpeg_muxer *stream)
223
+{
224
+   if (purge_front(stream)) {
225
+       struct encoder_packet pkt;
226
+
227
+       for (;;) {
228
+           circlebuf_peek_front(&stream->packets, &pkt,
229
+                   sizeof(pkt));
230
+           if (pkt.type == OBS_ENCODER_VIDEO && pkt.keyframe)
231
+               return;
232
+
233
+           purge_front(stream);
234
+       }
235
+   }
236
+}
237
+
238
+static inline void replay_buffer_purge(struct ffmpeg_muxer *stream,
239
+       struct encoder_packet *pkt)
240
+{
241
+   if (stream->max_size) {
242
+       if (!stream->packets.size || stream->keyframes <= 2)
243
+           return;
244
+
245
+       while ((stream->cur_size + (int64_t)pkt->size) >
246
+               stream->max_size)
247
+           purge(stream);
248
+   }
249
+
250
+   if (!stream->packets.size || stream->keyframes <= 2)
251
+       return;
252
+
253
+   while ((pkt->dts_usec - stream->cur_time) > stream->max_time)
254
+       purge(stream);
255
+}
256
+
257
+static void insert_packet(struct darray *array, struct encoder_packet *packet,
258
+       int64_t video_offset, int64_t *audio_offsets,
259
+       int64_t video_dts_offset, int64_t *audio_dts_offsets)
260
+{
261
+   struct encoder_packet pkt;
262
+   DARRAY(struct encoder_packet) packets;
263
+   packets.da = *array;
264
+   size_t idx;
265
+
266
+   obs_encoder_packet_ref(&pkt, packet);
267
+
268
+   if (pkt.type == OBS_ENCODER_VIDEO) {
269
+       pkt.dts_usec -= video_offset;
270
+       pkt.dts -= video_dts_offset;
271
+       pkt.pts -= video_dts_offset;
272
+   } else {
273
+       pkt.dts_usec -= audio_offsets[pkt.track_idx];
274
+       pkt.dts -= audio_dts_offsets[pkt.track_idx];
275
+       pkt.pts -= audio_dts_offsets[pkt.track_idx];
276
+   }
277
+
278
+   for (idx = packets.num; idx > 0; idx--) {
279
+       struct encoder_packet *p = packets.array + (idx - 1);
280
+       if (p->dts_usec < pkt.dts_usec)
281
+           break;
282
+   }
283
+
284
+   da_insert(packets, idx, &pkt);
285
+   *array = packets.da;
286
+}
287
+
288
+static void *replay_buffer_mux_thread(void *data)
289
+{
290
+   struct ffmpeg_muxer *stream = data;
291
+
292
+   start_pipe(stream, stream->path.array);
293
+
294
+   if (!stream->pipe) {
295
+       warn("Failed to create process pipe");
296
+       goto error;
297
+   }
298
+
299
+   if (!send_headers(stream)) {
300
+       warn("Could not write headers for file '%s'",
301
+               stream->path.array);
302
+       goto error;
303
+   }
304
+
305
+   for (size_t i = 0; i < stream->mux_packets.num; i++) {
306
+       struct encoder_packet *pkt = &stream->mux_packets.array[i];
307
+       write_packet(stream, pkt);
308
+       obs_encoder_packet_release(pkt);
309
+   }
310
+
311
+   info("Wrote replay buffer to '%s'", stream->path.array);
312
+
313
+error:
314
+   os_process_pipe_destroy(stream->pipe);
315
+   stream->pipe = NULL;
316
+   da_free(stream->mux_packets);
317
+   os_atomic_set_bool(&stream->muxing, false);
318
+   return NULL;
319
+}
320
+
321
+static void replay_buffer_save(struct ffmpeg_muxer *stream)
322
+{
323
+   const size_t size = sizeof(struct encoder_packet);
324
+   size_t num_packets = stream->packets.size / size;
325
+
326
+   da_reserve(stream->mux_packets, num_packets);
327
+
328
+   /* ---------------------------- */
329
+   /* reorder packets */
330
+
331
+   bool found_video = false;
332
+   bool found_audio[MAX_AUDIO_MIXES] = {0};
333
+   int64_t video_offset = 0;
334
+   int64_t video_dts_offset = 0;
335
+   int64_t audio_offsets[MAX_AUDIO_MIXES] = {0};
336
+   int64_t audio_dts_offsets[MAX_AUDIO_MIXES] = {0};
337
+
338
+   for (size_t i = 0; i < num_packets; i++) {
339
+       struct encoder_packet *pkt;
340
+       pkt = circlebuf_data(&stream->packets, i * size);
341
+
342
+       if (pkt->type == OBS_ENCODER_VIDEO) {
343
+           if (!found_video) {
344
+               video_offset = pkt->dts_usec;
345
+               video_dts_offset = pkt->dts;
346
+               found_video = true;
347
+           }
348
+       } else {
349
+           if (!found_audio[pkt->track_idx]) {
350
+               found_audio[pkt->track_idx] = true;
351
+               audio_offsets[pkt->track_idx] = pkt->dts_usec;
352
+               audio_dts_offsets[pkt->track_idx] = pkt->dts;
353
+           }
354
+       }
355
+
356
+       insert_packet(&stream->mux_packets.da, pkt,
357
+               video_offset, audio_offsets,
358
+               video_dts_offset, audio_dts_offsets);
359
+   }
360
+
361
+   /* ---------------------------- */
362
+   /* generate filename */
363
+
364
+   obs_data_t *settings = obs_output_get_settings(stream->output);
365
+   const char *dir = obs_data_get_string(settings, "directory");
366
+   const char *fmt = obs_data_get_string(settings, "format");
367
+   const char *ext = obs_data_get_string(settings, "extension");
368
+   bool space = obs_data_get_bool(settings, "allow_spaces");
369
+
370
+   char *filename = os_generate_formatted_filename(ext, space, fmt);
371
+
372
+   dstr_copy(&stream->path, dir);
373
+   dstr_replace(&stream->path, "\\", "/");
374
+   if (dstr_end(&stream->path) != '/')
375
+       dstr_cat_ch(&stream->path, '/');
376
+   dstr_cat(&stream->path, filename);
377
+
378
+   bfree(filename);
379
+   obs_data_release(settings);
380
+
381
+   /* ---------------------------- */
382
+
383
+   os_atomic_set_bool(&stream->muxing, true);
384
+   stream->mux_thread_joinable = pthread_create(&stream->mux_thread, NULL,
385
+           replay_buffer_mux_thread, stream) == 0;
386
+}
387
+
388
+static void deactivate_replay_buffer(struct ffmpeg_muxer *stream)
389
+{
390
+   if (stopping(stream))
391
+       obs_output_end_data_capture(stream->output);
392
+
393
+   os_atomic_set_bool(&stream->active, false);
394
+   os_atomic_set_bool(&stream->sent_headers, false);
395
+   os_atomic_set_bool(&stream->stopping, false);
396
+   replay_buffer_clear(stream);
397
+}
398
+
399
+static void replay_buffer_data(void *data, struct encoder_packet *packet)
400
+{
401
+   struct ffmpeg_muxer *stream = data;
402
+   struct encoder_packet pkt;
403
+
404
+   if (!active(stream))
405
+       return;
406
+
407
+   if (stopping(stream)) {
408
+       if (packet->sys_dts_usec >= stream->stop_ts) {
409
+           deactivate_replay_buffer(stream);
410
+           return;
411
+       }
412
+   }
413
+
414
+   obs_encoder_packet_ref(&pkt, packet);
415
+   replay_buffer_purge(stream, &pkt);
416
+
417
+   if (!stream->packets.size)
418
+       stream->cur_time = pkt.dts_usec;
419
+   stream->cur_size += pkt.size;
420
+
421
+   circlebuf_push_back(&stream->packets, packet, sizeof(*packet));
422
+
423
+   if (packet->type == OBS_ENCODER_VIDEO && packet->keyframe)
424
+       stream->keyframes++;
425
+
426
+   if (stream->save_ts && packet->sys_dts_usec >= stream->save_ts) {
427
+       if (os_atomic_load_bool(&stream->muxing))
428
+           return;
429
+
430
+       if (stream->mux_thread_joinable) {
431
+           pthread_join(stream->mux_thread, NULL);
432
+           stream->mux_thread_joinable = false;
433
+       }
434
+
435
+       stream->save_ts = 0;
436
+       replay_buffer_save(stream);
437
+   }
438
+}
439
+
440
+static void replay_buffer_defaults(obs_data_t *s)
441
+{
442
+   obs_data_set_default_int(s, "max_time_sec", 15);
443
+   obs_data_set_default_int(s, "max_size_mb", 500);
444
+   obs_data_set_default_string(s, "format", "%CCYY-%MM-%DD %hh-%mm-%ss");
445
+   obs_data_set_default_string(s, "extension", "mp4");
446
+   obs_data_set_default_bool(s, "allow_spaces", true);
447
+}
448
+
449
+struct obs_output_info replay_buffer = {
450
+   .id             = "replay_buffer",
451
+   .flags          = OBS_OUTPUT_AV |
452
+                     OBS_OUTPUT_ENCODED |
453
+                     OBS_OUTPUT_MULTI_TRACK,
454
+   .get_name       = replay_buffer_getname,
455
+   .create         = replay_buffer_create,
456
+   .destroy        = replay_buffer_destroy,
457
+   .start          = replay_buffer_start,
458
+   .stop           = ffmpeg_mux_stop,
459
+   .encoded_packet = replay_buffer_data,
460
+   .get_defaults   = replay_buffer_defaults
461
+};
462
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c Changed
12
 
1
@@ -272,7 +272,9 @@
2
 
3
    enc = bzalloc(sizeof(*enc));
4
    enc->encoder = encoder;
5
-   enc->nvenc = avcodec_find_encoder_by_name("nvenc_h264");
6
+   enc->nvenc = avcodec_find_encoder_by_name("h264_nvenc");
7
+   if (!enc->nvenc)
8
+       enc->nvenc = avcodec_find_encoder_by_name("nvenc_h264");
9
    enc->first_packet = true;
10
 
11
    blog(LOG_INFO, "---------------------------------");
12
obs-studio-0.16.6.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg.c -> obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg.c Changed
17
 
1
@@ -11,6 +11,7 @@
2
 extern struct obs_source_info  ffmpeg_source;
3
 extern struct obs_output_info  ffmpeg_output;
4
 extern struct obs_output_info  ffmpeg_muxer;
5
+extern struct obs_output_info  replay_buffer;
6
 extern struct obs_encoder_info aac_encoder_info;
7
 extern struct obs_encoder_info nvenc_encoder_info;
8
 
9
@@ -145,6 +146,7 @@
10
    obs_register_source(&ffmpeg_source);
11
    obs_register_output(&ffmpeg_output);
12
    obs_register_output(&ffmpeg_muxer);
13
+   obs_register_output(&replay_buffer);
14
    obs_register_encoder(&aac_encoder_info);
15
    if (nvenc_supported()) {
16
        blog(LOG_INFO, "NVENC supported");
17
obs-studio-0.16.6.tar.xz/plugins/obs-filters/CMakeLists.txt -> obs-studio-0.17.0.tar.xz/plugins/obs-filters/CMakeLists.txt Changed
10
 
1
@@ -20,7 +20,7 @@
2
 
3
 set(obs-filters_SOURCES
4
    obs-filters.c
5
-   color-filter.c
6
+   color-correction-filter.c
7
    async-delay-filter.c
8
    crop-filter.c
9
    scale-filter.c
10
obs-studio-0.17.0.tar.xz/plugins/obs-filters/color-correction-filter.c Added
408
 
1
@@ -0,0 +1,406 @@
2
+/*****************************************************************************
3
+Copyright (C) 2016 by c3r1c3 <c3r1c3@nevermindonline.com>
4
+
5
+This program is free software: you can redistribute it and/or modify
6
+it under the terms of the GNU General Public License as published by
7
+the Free Software Foundation, either version 2 of the License, or
8
+(at your option) any later version.
9
+
10
+This program is distributed in the hope that it will be useful,
11
+but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+GNU General Public License for more details.
14
+
15
+You should have received a copy of the GNU General Public License
16
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
+*****************************************************************************/
18
+#include <obs-module.h>
19
+#include <graphics/matrix4.h>
20
+#include <graphics/quat.h>
21
+
22
+
23
+#define SETTING_GAMMA                  "gamma"
24
+#define SETTING_CONTRAST               "contrast"
25
+#define SETTING_BRIGHTNESS             "brightness"
26
+#define SETTING_SATURATION             "saturation"
27
+#define SETTING_HUESHIFT               "hue_shift"
28
+#define SETTING_OPACITY                "opacity"
29
+#define SETTING_COLOR                  "color"
30
+
31
+#define TEXT_GAMMA                     obs_module_text("Gamma")
32
+#define TEXT_CONTRAST                  obs_module_text("Contrast")
33
+#define TEXT_BRIGHTNESS                obs_module_text("Brightness")
34
+#define TEXT_SATURATION                obs_module_text("Saturation")
35
+#define TEXT_HUESHIFT                  obs_module_text("HueShift")
36
+#define TEXT_OPACITY                   obs_module_text("Opacity")
37
+#define TEXT_COLOR                     obs_module_text("Color")
38
+
39
+struct color_correction_filter_data {
40
+   obs_source_t                   *context;
41
+
42
+   gs_effect_t                    *effect;
43
+
44
+   gs_eparam_t                    *gamma_param;
45
+   gs_eparam_t                    *final_matrix_param;
46
+
47
+   struct vec3                     gamma;
48
+   float                           contrast;
49
+   float                           brightness;
50
+   float                           saturation;
51
+   float                           hue_shift;
52
+   float                           opacity;
53
+   struct vec4                     color;
54
+
55
+   /* Pre-Computes */
56
+   struct matrix4                  con_matrix;
57
+   struct matrix4                  bright_matrix;
58
+   struct matrix4                  sat_matrix;
59
+   struct matrix4                  hue_op_matrix;
60
+   struct matrix4                  color_matrix;
61
+   struct matrix4                  final_matrix;
62
+
63
+   struct vec3                     rot_quaternion;
64
+   float                           rot_quaternion_w;
65
+   struct vec3                     cross;
66
+   struct vec3                     square;
67
+   struct vec3                     wimag;
68
+   struct vec3                     diag;
69
+   struct vec3                     a_line;
70
+   struct vec3                     b_line;
71
+   struct vec3                     half_unit;
72
+};
73
+
74
+const static float root3 = 0.57735f;
75
+
76
+/*
77
+ * As the functions' namesake, this provides the internal name of your Filter,
78
+ * which is then translated/referenced in the "data/locale" files.
79
+ */
80
+static const char *color_correction_filter_name(void *unused)
81
+{
82
+   UNUSED_PARAMETER(unused);
83
+   return obs_module_text("ColorFilter");
84
+}
85
+
86
+/*
87
+ * This function is called (see bottom of this file for more details)
88
+ * whenever the OBS filter interface changes. So when the user is messing
89
+ * with a slider this function is called to update the internal settings
90
+ * in OBS, and hence the settings being passed to the CPU/GPU.
91
+ */
92
+static void color_correction_filter_update(void *data, obs_data_t *settings)
93
+{
94
+   struct color_correction_filter_data *filter = data;
95
+
96
+   /* Build our Gamma numbers. */
97
+   double gamma = obs_data_get_double(settings, SETTING_GAMMA);
98
+   gamma = (gamma < 0.0) ? (-gamma + 1.0) : (1.0 / (gamma + 1.0));
99
+   vec3_set(&filter->gamma, (float)gamma, (float)gamma, (float)gamma);
100
+
101
+   /* Build our contrast number. */
102
+   filter->contrast = (float)obs_data_get_double(settings,
103
+           SETTING_CONTRAST) + 1.0f;
104
+   float one_minus_con = (1.0f - filter->contrast) / 2.0f;
105
+
106
+   /* Now let's build our Contrast matrix. */
107
+   filter->con_matrix = (struct matrix4)
108
+   {
109
+       filter->contrast, 0.0f, 0.0f, 0.0f,
110
+       0.0f, filter->contrast, 0.0f, 0.0f,
111
+       0.0f, 0.0f, filter->contrast, 0.0f,
112
+       one_minus_con, one_minus_con, one_minus_con, 1.0f
113
+   };
114
+
115
+   /* Build our brightness number. */
116
+   filter->brightness = (float)obs_data_get_double(settings,
117
+           SETTING_BRIGHTNESS);
118
+
119
+   /*
120
+    * Now let's build our Brightness matrix.
121
+    * Earlier (in the function color_correction_filter_create) we set
122
+    * this matrix to the identity matrix, so now we only need
123
+    * to set the 3 variables that have changed.
124
+    */
125
+   filter->bright_matrix.t.x = filter->brightness;
126
+   filter->bright_matrix.t.y = filter->brightness;
127
+   filter->bright_matrix.t.z = filter->brightness;
128
+
129
+   /* Build our Saturation number. */
130
+   filter->saturation = (float)obs_data_get_double(settings,
131
+           SETTING_SATURATION) + 1.0f;
132
+
133
+   /* Factor in the selected color weights. */
134
+   float one_minus_sat = (1.0f - filter->saturation) / 3.0f;
135
+   float sat_val = one_minus_sat + filter->saturation;
136
+
137
+   /* Now we build our Saturation matrix. */
138
+   filter->sat_matrix = (struct matrix4)
139
+   {
140
+       sat_val, one_minus_sat, one_minus_sat, 0.0f,
141
+       one_minus_sat, sat_val, one_minus_sat, 0.0f,
142
+       one_minus_sat, one_minus_sat, sat_val, 0.0f,
143
+       0.0f, 0.0f, 0.0f, 1.0f
144
+   };
145
+
146
+   /* Build our Hue number. */
147
+   filter->hue_shift = (float)obs_data_get_double(settings,
148
+           SETTING_HUESHIFT);
149
+
150
+   /* Build our Transparency number. */
151
+   filter->opacity = (float)obs_data_get_int(settings,
152
+           SETTING_OPACITY) * 0.01f;
153
+
154
+   /* Hue is the radian of 0 to 360 degrees. */
155
+   float half_angle = 0.5f * (float)(filter->hue_shift / (180.0f / M_PI));
156
+
157
+   /* Pseudo-Quaternion To Matrix. */
158
+   float rot_quad1 = root3 * (float)sin(half_angle);
159
+   vec3_set(&filter->rot_quaternion, rot_quad1, rot_quad1,
160
+           rot_quad1);
161
+   filter->rot_quaternion_w = (float)cos(half_angle);
162
+
163
+   vec3_mul(&filter->cross, &filter->rot_quaternion,
164
+           &filter->rot_quaternion);
165
+   vec3_mul(&filter->square, &filter->rot_quaternion,
166
+           &filter->rot_quaternion);
167
+   vec3_mulf(&filter->wimag, &filter->rot_quaternion,
168
+           filter->rot_quaternion_w);
169
+
170
+   vec3_mulf(&filter->square, &filter->square, 2.0f);
171
+   vec3_sub(&filter->diag, &filter->half_unit, &filter->square);
172
+   vec3_add(&filter->a_line, &filter->cross, &filter->wimag);
173
+   vec3_sub(&filter->b_line, &filter->cross, &filter->wimag);
174
+
175
+   /* Now we build our Hue and Opacity matrix. */
176
+   filter->hue_op_matrix = (struct matrix4)
177
+   {
178
+       filter->diag.x * 2.0f,
179
+       filter->b_line.z * 2.0f,
180
+       filter->a_line.y * 2.0f,
181
+       0.0f,
182
+
183
+       filter->a_line.z * 2.0f,
184
+       filter->diag.y * 2.0f,
185
+       filter->b_line.x * 2.0f,
186
+       0.0f,
187
+
188
+       filter->b_line.y * 2.0f,
189
+       filter->a_line.x * 2.0f,
190
+       filter->diag.z * 2.0f,
191
+       0.0f,
192
+
193
+       0.0f, 0.0f, 0.0f, filter->opacity
194
+   };
195
+
196
+   /* Now get the overlay color data. */
197
+   uint32_t color = (uint32_t)obs_data_get_int(settings,
198
+           SETTING_COLOR);
199
+   vec4_from_rgba(&filter->color, color);
200
+
201
+   /*
202
+   * Now let's build our Color 'overlay' matrix.
203
+   * Earlier (in the function color_correction_filter_create) we set
204
+   * this matrix to the identity matrix, so now we only need
205
+   * to set the 6 variables that have changed.
206
+   */
207
+   filter->color_matrix.x.x = filter->color.x;
208
+   filter->color_matrix.y.y = filter->color.y;
209
+   filter->color_matrix.z.z = filter->color.z;
210
+
211
+   filter->color_matrix.t.x = filter->color.w *
212
+           filter->color.x;
213
+   filter->color_matrix.t.y = filter->color.w *
214
+           filter->color.y;
215
+   filter->color_matrix.t.z = filter->color.w *
216
+           filter->color.z;
217
+
218
+
219
+   /* First we apply the Contrast & Brightness matrix. */
220
+   matrix4_mul(&filter->final_matrix, &filter->bright_matrix,
221
+           &filter->con_matrix);
222
+   /* Now we apply the Saturation matrix. */
223
+   matrix4_mul(&filter->final_matrix, &filter->final_matrix,
224
+           &filter->sat_matrix);
225
+   /* Next we apply the Hue+Opacity matrix. */
226
+   matrix4_mul(&filter->final_matrix, &filter->final_matrix,
227
+           &filter->hue_op_matrix);
228
+   /* Lastly we apply the Color Wash matrix. */
229
+   matrix4_mul(&filter->final_matrix, &filter->final_matrix,
230
+           &filter->color_matrix);
231
+}
232
+
233
+/*
234
+ * Since this is C we have to be careful when destroying/removing items from
235
+ * OBS. Jim has added several useful functions to help keep memory leaks to
236
+ * a minimum, and handle the destruction and construction of these filters.
237
+ */
238
+static void color_correction_filter_destroy(void *data)
239
+{
240
+   struct color_correction_filter_data *filter = data;
241
+
242
+   if (filter->effect) {
243
+       obs_enter_graphics();
244
+       gs_effect_destroy(filter->effect);
245
+       obs_leave_graphics();
246
+   }
247
+
248
+   bfree(data);
249
+}
250
+
251
+/*
252
+ * When you apply a filter OBS creates it, and adds it to the source. OBS also
253
+ * starts rendering it immediately. This function doesn't just 'create' the
254
+ * filter, it also calls the render function (farther below) that contains the
255
+ * actual rendering code.
256
+ */
257
+static void *color_correction_filter_create(obs_data_t *settings,
258
+   obs_source_t *context)
259
+{
260
+   /*
261
+   * Because of limitations of pre-c99 compilers, you can't create an
262
+   * array that doesn't have a known size at compile time. The below
263
+   * function calculates the size needed and allocates memory to
264
+   * handle the source.
265
+   */
266
+   struct color_correction_filter_data *filter =
267
+       bzalloc(sizeof(struct color_correction_filter_data));
268
+
269
+   /*
270
+    * By default the effect file is stored in the ./data directory that
271
+    * your filter resides in.
272
+    */
273
+   char *effect_path = obs_module_file("color_correction_filter.effect");
274
+
275
+   filter->context = context;
276
+
277
+   /* Set/clear/assign for all necessary vectors. */
278
+   vec3_set(&filter->half_unit, 0.5f, 0.5f, 0.5f);
279
+   matrix4_identity(&filter->bright_matrix);
280
+   matrix4_identity(&filter->color_matrix);
281
+
282
+   /* Here we enter the GPU drawing/shader portion of our code. */
283
+   obs_enter_graphics();
284
+
285
+   /* Load the shader on the GPU. */
286
+   filter->effect = gs_effect_create_from_file(effect_path, NULL);
287
+
288
+   /* If the filter is active pass the parameters to the filter. */
289
+   if (filter->effect) {
290
+       filter->gamma_param = gs_effect_get_param_by_name(
291
+               filter->effect, SETTING_GAMMA);
292
+       filter->final_matrix_param = gs_effect_get_param_by_name(
293
+               filter->effect, "color_matrix");
294
+   }
295
+
296
+   obs_leave_graphics();
297
+
298
+   bfree(effect_path);
299
+
300
+   /*
301
+    * If the filter has been removed/deactivated, destroy the filter
302
+    * and exit out so we don't crash OBS by telling it to update
303
+    * values that don't exist anymore.
304
+    */
305
+   if (!filter->effect) {
306
+       color_correction_filter_destroy(filter);
307
+       return NULL;
308
+   }
309
+
310
+   /*
311
+    * It's important to call the update function here. If we don't
312
+    * we could end up with the user controlled sliders and values
313
+    * updating, but the visuals not updating to match.
314
+    */
315
+   color_correction_filter_update(filter, settings);
316
+   return filter;
317
+}
318
+
319
+/* This is where the actual rendering of the filter takes place. */
320
+static void color_correction_filter_render(void *data, gs_effect_t *effect)
321
+{
322
+   struct color_correction_filter_data *filter = data;
323
+
324
+   if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
325
+           OBS_ALLOW_DIRECT_RENDERING))
326
+       return;
327
+
328
+   /* Now pass the interface variables to the .effect file. */
329
+   gs_effect_set_vec3(filter->gamma_param, &filter->gamma);
330
+   gs_effect_set_matrix4(filter->final_matrix_param, &filter->final_matrix);
331
+
332
+   obs_source_process_filter_end(filter->context, filter->effect, 0, 0);
333
+
334
+   UNUSED_PARAMETER(effect);
335
+}
336
+
337
+/*
338
+ * This function sets the interface. the types (add_*_Slider), the type of
339
+ * data collected (int), the internal name, user-facing name, minimum,
340
+ * maximum and step values. While a custom interface can be built, for a
341
+ * simple filter like this it's better to use the supplied functions.
342
+ */
343
+static obs_properties_t *color_correction_filter_properties(void *data)
344
+{
345
+   obs_properties_t *props = obs_properties_create();
346
+
347
+   obs_properties_add_float_slider(props, SETTING_GAMMA,
348
+           TEXT_GAMMA, -3.0f, 3.0f, 0.01f);
349
+
350
+   obs_properties_add_float_slider(props, SETTING_CONTRAST,
351
+           TEXT_CONTRAST, -2.0f, 2.0f, 0.01f);
352
+   obs_properties_add_float_slider(props, SETTING_BRIGHTNESS,
353
+           TEXT_BRIGHTNESS, -1.0f, 1.0f, 0.01f);
354
+   obs_properties_add_float_slider(props, SETTING_SATURATION,
355
+           TEXT_SATURATION, -1.0f, 5.0f, 0.01f);
356
+   obs_properties_add_float_slider(props, SETTING_HUESHIFT,
357
+           TEXT_HUESHIFT, -180.0f, 180.0f, 0.01f);
358
+   obs_properties_add_int_slider(props, SETTING_OPACITY,
359
+           TEXT_OPACITY, 0, 100, 1);
360
+
361
+   obs_properties_add_color(props, SETTING_COLOR, TEXT_COLOR);
362
+
363
+   UNUSED_PARAMETER(data);
364
+   return props;
365
+}
366
+
367
+/*
368
+ * As the functions' namesake, this provides the default settings for any
369
+ * options you wish to provide a default for. Try to select defaults that
370
+ * make sense to the end user, or that don't effect the data.
371
+ * *NOTE* this function is completely optional, as is providing a default
372
+ * for any particular setting.
373
+ */
374
+static void color_correction_filter_defaults(obs_data_t *settings)
375
+{
376
+   obs_data_set_default_double(settings, SETTING_GAMMA, 0.0);
377
+   obs_data_set_default_double(settings, SETTING_CONTRAST, 0.0);
378
+   obs_data_set_default_double(settings, SETTING_BRIGHTNESS, 0.0);
379
+   obs_data_set_default_double(settings,
380
+           SETTING_SATURATION, 0.0);
381
+   obs_data_set_default_double(settings, SETTING_HUESHIFT, 0.0);
382
+   obs_data_set_default_double(settings, SETTING_OPACITY, 100.0);
383
+   obs_data_set_default_int(settings, SETTING_COLOR, 0xFFFFFF);
384
+}
385
+
386
+/*
387
+ * So how does OBS keep track of all these plug-ins/filters? How does OBS know
388
+ * which function to call when it needs to update a setting? Or a source? Or
389
+ * what type of source this is?
390
+ *
391
+ * OBS does it through the obs_source_info_struct. Notice how variables are
392
+ * assigned the name of a function? Notice how the function name has the
393
+ * variable name in it? While not mandatory, it helps a ton for you (and those
394
+ * reading your code) to follow this convention.
395
+ */
396
+struct obs_source_info color_filter = {
397
+   .id = "color_filter",
398
+   .type = OBS_SOURCE_TYPE_FILTER,
399
+   .output_flags = OBS_SOURCE_VIDEO,
400
+   .get_name = color_correction_filter_name,
401
+   .create = color_correction_filter_create,
402
+   .destroy = color_correction_filter_destroy,
403
+   .video_render = color_correction_filter_render,
404
+   .update = color_correction_filter_update,
405
+   .get_properties = color_correction_filter_properties,
406
+   .get_defaults = color_correction_filter_defaults
407
+};
408
obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/color_correction_filter.effect Added
80
 
1
@@ -0,0 +1,78 @@
2
+/*****************************************************************************
3
+Copyright (C) 2016 by c3r1c3 <c3r1c3@nevermindonline.com>
4
+
5
+This program is free software: you can redistribute it and/or modify
6
+it under the terms of the GNU General Public License as published by
7
+the Free Software Foundation, either version 2 of the License, or
8
+(at your option) any later version.
9
+
10
+This program is distributed in the hope that it will be useful,
11
+but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+GNU General Public License for more details.
14
+
15
+You should have received a copy of the GNU General Public License
16
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
+*****************************************************************************/
18
+
19
+uniform float4x4 ViewProj;
20
+uniform texture2d image;
21
+
22
+uniform float3 gamma;
23
+
24
+/* Pre-Compute variables. */
25
+uniform float4x4 color_matrix;
26
+
27
+
28
+sampler_state textureSampler {
29
+   Filter   = Linear;
30
+   AddressU = Clamp;
31
+   AddressV = Clamp;
32
+};
33
+
34
+struct VertData {
35
+   float4 pos : POSITION;
36
+   float2 uv : TEXCOORD0;
37
+};
38
+
39
+struct CurrentPixel {
40
+   float4 current_pixel;
41
+};
42
+
43
+VertData VSDefault(VertData vert_in)
44
+{
45
+   VertData vert_out;
46
+   vert_out.pos = mul(float4(vert_in.pos.xyz, 1.0), ViewProj);
47
+   vert_out.uv = vert_in.uv;
48
+   return vert_out;
49
+}
50
+
51
+float4 PSColorFilterRGBA(VertData vert_in) : TARGET
52
+{
53
+   /* Realize the struct. */
54
+   CurrentPixel pixel = (CurrentPixel) 0;
55
+
56
+   /* Grab the current pixel to perform operations on. */
57
+   pixel.current_pixel = image.Sample(textureSampler, vert_in.uv);
58
+
59
+   /* Always address the gamma first. */
60
+   pixel.current_pixel.rgb = pow(pixel.current_pixel.rgb, gamma);
61
+
62
+   /* Much easier to manipulate pixels for these types of operations
63
+    * when in a matrix such as the below. See
64
+    * http://www.graficaobscura.com/matrix/index.html and
65
+    * https://docs.rainmeter.net/tips/colormatrix-guide/for more info.
66
+    */
67
+   pixel.current_pixel = mul(color_matrix, pixel.current_pixel);
68
+
69
+   return pixel.current_pixel;
70
+}
71
+
72
+technique Draw
73
+{
74
+   pass
75
+   {
76
+       vertex_shader = VSDefault(vert_in);
77
+       pixel_shader = PSColorFilterRGBA(vert_in);
78
+   }
79
+}
80
obs-studio-0.16.6.tar.xz/plugins/obs-filters/data/locale/da-DK.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/da-DK.ini Changed
38
 
1
@@ -1,11 +1,14 @@
2
 ColorFilter="Farvekorrektion"
3
 MaskFilter="Billede maske/blanding"
4
 AsyncDelayFilter="Video forsinkelse (asynkron)"
5
+CropFilter="Beskæring/Polstring"
6
 ScrollFilter="Rul"
7
 ChromaKeyFilter="Chroma nøgle"
8
 ColorKeyFilter="Farvenøgle"
9
 SharpnessFilter="Skarphed"
10
+ScaleFilter="Skalering/Formatforhold"
11
 NoiseGate="Noise Gate"
12
+NoiseSuppress="Støjundertrykkelse"
13
 Gain="Forstærkning"
14
 DelayMs="Forsinkelse (millisekunder)"
15
 Type="Type"
16
@@ -43,6 +46,21 @@
17
 Green="Grøn"
18
 Blue="Blå"
19
 Magenta="Magenta"
20
+NoiseGate.OpenThreshold="Åbne-tærskel (dB)"
21
+NoiseGate.CloseThreshold="Lukke-tærskel (dB)"
22
+NoiseGate.AttackTime="Effektueringstid (millisek.)"
23
+NoiseGate.HoldTime="Holdetid (millisek.)"
24
+NoiseGate.ReleaseTime="Frigivelsestid (millisek.)"
25
 Gain.GainDB="Forstærkning (dB)"
26
 StretchImage="Stræk billedet (ignorer størrelsesforhold)"
27
+Resolution="Opløsning"
28
+None="Ingen"
29
+ScaleFiltering="Skaleringsfilter"
30
+ScaleFiltering.Point="Punkt"
31
+ScaleFiltering.Bilinear="Bilineær"
32
+ScaleFiltering.Bicubic="Bikubisk"
33
+ScaleFiltering.Lanczos="Lanczos"
34
+NoiseSuppress.SuppressLevel="Undertrykkelsesniveau (dB)"
35
+Saturation="Mætning"
36
+HueShift="Nuanceskift"
37
 
38
obs-studio-0.16.6.tar.xz/plugins/obs-filters/data/locale/de-DE.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/de-DE.ini Changed
8
 
1
@@ -61,4 +61,6 @@
2
 ScaleFiltering.Bicubic="Bicubic"
3
 ScaleFiltering.Lanczos="Lanczos"
4
 NoiseSuppress.SuppressLevel="Unterdrückungspegel (dB)"
5
+Saturation="Sättigung"
6
+HueShift="Farbtonverschiebung"
7
 
8
obs-studio-0.16.6.tar.xz/plugins/obs-filters/data/locale/en-US.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/en-US.ini Changed
7
 
1
@@ -61,3 +61,5 @@
2
 ScaleFiltering.Bicubic="Bicubic"
3
 ScaleFiltering.Lanczos="Lanczos"
4
 NoiseSuppress.SuppressLevel="Suppression Level (dB)"
5
+Saturation="Saturation"
6
+HueShift="Hue Shift"
7
obs-studio-0.16.6.tar.xz/plugins/obs-filters/data/locale/es-ES.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/es-ES.ini Changed
8
 
1
@@ -61,4 +61,6 @@
2
 ScaleFiltering.Bicubic="Bicúbico"
3
 ScaleFiltering.Lanczos="Lanczos"
4
 NoiseSuppress.SuppressLevel="Nivel de eliminación de ruido (dB)"
5
+Saturation="Saturación"
6
+HueShift="Cambio de tonalidad"
7
 
8
obs-studio-0.16.6.tar.xz/plugins/obs-filters/data/locale/fr-FR.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/fr-FR.ini Changed
8
 
1
@@ -61,4 +61,6 @@
2
 ScaleFiltering.Bicubic="Bicubique"
3
 ScaleFiltering.Lanczos="Lanczos"
4
 NoiseSuppress.SuppressLevel="Seuil de suppression (en dB)"
5
+Saturation="Saturation"
6
+HueShift="Décalage de teinte"
7
 
8
obs-studio-0.16.6.tar.xz/plugins/obs-filters/data/locale/hu-HU.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/hu-HU.ini Changed
8
 
1
@@ -61,4 +61,6 @@
2
 ScaleFiltering.Bicubic="Kettős köbös"
3
 ScaleFiltering.Lanczos="Lanczos"
4
 NoiseSuppress.SuppressLevel="Csökkentési szint (dB)"
5
+Saturation="Telítettség"
6
+HueShift="Színezet váltása"
7
 
8
obs-studio-0.16.6.tar.xz/plugins/obs-filters/data/locale/ja-JP.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/ja-JP.ini Changed
8
 
1
@@ -61,4 +61,6 @@
2
 ScaleFiltering.Bicubic="バイキュービック"
3
 ScaleFiltering.Lanczos="ランチョス"
4
 NoiseSuppress.SuppressLevel="抑制レベル (dB)"
5
+Saturation="彩度"
6
+HueShift="色相シフト"
7
 
8
obs-studio-0.16.6.tar.xz/plugins/obs-filters/data/locale/ko-KR.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/ko-KR.ini Changed
8
 
1
@@ -61,4 +61,6 @@
2
 ScaleFiltering.Bicubic="쌍삼차"
3
 ScaleFiltering.Lanczos="란초스"
4
 NoiseSuppress.SuppressLevel="억제 세기 (dB)"
5
+Saturation="채도"
6
+HueShift="색조 변화"
7
 
8
obs-studio-0.16.6.tar.xz/plugins/obs-filters/data/locale/nl-NL.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/nl-NL.ini Changed
8
 
1
@@ -61,4 +61,6 @@
2
 ScaleFiltering.Bicubic="Bicubic"
3
 ScaleFiltering.Lanczos="Lanczos"
4
 NoiseSuppress.SuppressLevel="Onderdrukkingsniveau (dB)"
5
+Saturation="Verzadiging"
6
+HueShift="Tintverschuiving"
7
 
8
obs-studio-0.16.6.tar.xz/plugins/obs-filters/data/locale/pl-PL.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/pl-PL.ini Changed
8
 
1
@@ -61,4 +61,6 @@
2
 ScaleFiltering.Bicubic="Dwusześcienne"
3
 ScaleFiltering.Lanczos="Lanczos"
4
 NoiseSuppress.SuppressLevel="Poziom tłumienia (dB)"
5
+Saturation="Nasycenie"
6
+HueShift="Przesunięcie barwy"
7
 
8
obs-studio-0.16.6.tar.xz/plugins/obs-filters/data/locale/tr-TR.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/tr-TR.ini Changed
30
 
1
@@ -6,6 +6,7 @@
2
 ColorKeyFilter="Renk Anahtarı"
3
 SharpnessFilter="Keskinleştirme"
4
 NoiseGate="Gürültü Filtresi"
5
+NoiseSuppress="Gürültü Bastırma"
6
 Gain="Kazanç"
7
 DelayMs="Gecikme (milisaniye)"
8
 Type="Türü"
9
@@ -20,7 +21,7 @@
10
 Contrast="Karşıtlık"
11
 Brightness="Parlaklık"
12
 Gamma="Gama"
13
-BrowsePath.Images="Tüm Resim Dosyaları"
14
+BrowsePath.Images="Tüm Görüntü Dosyaları"
15
 BrowsePath.AllFiles="Tüm Dosyalar"
16
 KeyColorType="Anahtar Renk Türü"
17
 KeyColor="Anahtar Renk"
18
@@ -49,4 +50,11 @@
19
 NoiseGate.HoldTime="Kavrama Süresi (milisaniye)"
20
 NoiseGate.ReleaseTime="Bırakma Süresi (milisaniye)"
21
 Gain.GainDB="Kazanç (dB)"
22
+Resolution="Çözünürlük"
23
+None="Hiçbiri"
24
+ScaleFiltering="Ölçek Filtreleme"
25
+ScaleFiltering.Point="Nokta"
26
+ScaleFiltering.Bilinear="Bilinear"
27
+ScaleFiltering.Bicubic="Bicubic"
28
+ScaleFiltering.Lanczos="Lanczos"
29
 
30
obs-studio-0.16.6.tar.xz/plugins/obs-filters/data/locale/zh-CN.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/zh-CN.ini Changed
8
 
1
@@ -61,4 +61,6 @@
2
 ScaleFiltering.Bicubic="双立方算法"
3
 ScaleFiltering.Lanczos="兰索斯算法"
4
 NoiseSuppress.SuppressLevel="抑制程度 (dB)"
5
+Saturation="饱和度"
6
+HueShift="色调偏移"
7
 
8
obs-studio-0.16.6.tar.xz/plugins/obs-filters/data/locale/zh-TW.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/zh-TW.ini Changed
8
 
1
@@ -61,4 +61,6 @@
2
 ScaleFiltering.Bicubic="雙三次插值"
3
 ScaleFiltering.Lanczos="Lanczos"
4
 NoiseSuppress.SuppressLevel="抑制標準 (dB)"
5
+Saturation="飽合度"
6
+HueShift="色調偏移"
7
 
8
obs-studio-0.16.6.tar.xz/plugins/obs-outputs/data/locale/da-DK.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-outputs/data/locale/da-DK.ini Changed
7
 
1
@@ -2,4 +2,5 @@
2
 RTMPStream.DropThreshold="Drop Tærskel (millisekunder)"
3
 FLVOutput="FLV File Output"
4
 FLVOutput.FilePath="Filsti"
5
+Default="Standard"
6
 
7
obs-studio-0.16.6.tar.xz/plugins/obs-outputs/data/locale/tr-TR.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-outputs/data/locale/tr-TR.ini Changed
7
 
1
@@ -2,4 +2,5 @@
2
 RTMPStream.DropThreshold="Düşürme Eşiği (milisaniye)"
3
 FLVOutput="FLV Dosyası Çıkışı"
4
 FLVOutput.FilePath="Dosya Yolu"
5
+Default="Varsayılan"
6
 
7
obs-studio-0.16.6.tar.xz/plugins/obs-outputs/flv-output.c -> obs-studio-0.17.0.tar.xz/plugins/obs-outputs/flv-output.c Changed
19
 
1
@@ -100,7 +100,7 @@
2
    flv_packet_mux(packet, &data, &size, is_header);
3
    fwrite(data, 1, size, stream->file);
4
    bfree(data);
5
-   obs_free_encoder_packet(packet);
6
+   obs_encoder_packet_release(packet);
7
 
8
    return ret;
9
 }
10
@@ -200,7 +200,7 @@
11
    if (packet->type == OBS_ENCODER_VIDEO) {
12
        obs_parse_avc_packet(&parsed_packet, packet);
13
        write_packet(stream, &parsed_packet, false);
14
-       obs_free_encoder_packet(&parsed_packet);
15
+       obs_encoder_packet_release(&parsed_packet);
16
    } else {
17
        write_packet(stream, packet, false);
18
    }
19
obs-studio-0.16.6.tar.xz/plugins/obs-outputs/librtmp/rtmp.c -> obs-studio-0.17.0.tar.xz/plugins/obs-outputs/librtmp/rtmp.c Changed
67
 
1
@@ -650,7 +650,7 @@
2
 }
3
 
4
 static int
5
-add_addr_info(struct sockaddr_storage *service, socklen_t *addrlen, AVal *host, int port)
6
+add_addr_info(struct sockaddr_storage *service, socklen_t *addrlen, AVal *host, int port, socklen_t addrlen_hint)
7
 {
8
     char *hostname;
9
     int ret = TRUE;
10
@@ -698,7 +698,7 @@
11
     // prefer ipv4 results, since lots of ISPs have broken ipv6 connectivity
12
     for (ptr = result; ptr != NULL; ptr = ptr->ai_next)
13
     {
14
-        if (ptr->ai_family == AF_INET)
15
+        if (ptr->ai_family == AF_INET && (!addrlen_hint || ptr->ai_addrlen == addrlen_hint))
16
         {
17
             memcpy(service, ptr->ai_addr, ptr->ai_addrlen);
18
             *addrlen = (socklen_t)ptr->ai_addrlen;
19
@@ -710,7 +710,7 @@
20
    {
21
        for (ptr = result; ptr != NULL; ptr = ptr->ai_next)
22
        {
23
-           if (ptr->ai_family == AF_INET6)
24
+            if (ptr->ai_family == AF_INET6 && (!addrlen_hint || ptr->ai_addrlen == addrlen_hint))
25
            {
26
                memcpy(service, ptr->ai_addr, ptr->ai_addrlen);
27
                *addrlen = (socklen_t)ptr->ai_addrlen;
28
@@ -905,6 +905,7 @@
29
 #endif
30
     struct sockaddr_storage service;
31
     socklen_t addrlen = 0;
32
+    socklen_t addrlen_hint = 0;
33
     if (!r->Link.hostname.av_len)
34
         return FALSE;
35
 
36
@@ -920,16 +921,19 @@
37
 
38
     memset(&service, 0, sizeof(service));
39
 
40
+    if (r->m_bindIP.addrLen)
41
+        addrlen_hint = r->m_bindIP.addrLen;
42
+
43
     if (r->Link.socksport)
44
     {
45
         /* Connect via SOCKS */
46
-        if (!add_addr_info(&service, &addrlen, &r->Link.sockshost, r->Link.socksport))
47
+        if (!add_addr_info(&service, &addrlen, &r->Link.sockshost, r->Link.socksport, addrlen_hint))
48
             return FALSE;
49
     }
50
     else
51
     {
52
         /* Connect directly */
53
-        if (!add_addr_info(&service, &addrlen, &r->Link.hostname, r->Link.port))
54
+        if (!add_addr_info(&service, &addrlen, &r->Link.hostname, r->Link.port, addrlen_hint))
55
             return FALSE;
56
     }
57
 
58
@@ -949,7 +953,7 @@
59
     socklen_t addrlen = 0;
60
     memset(&service, 0, sizeof(service));
61
 
62
-    add_addr_info(&service, &addrlen, &r->Link.hostname, r->Link.port);
63
+    add_addr_info(&service, &addrlen, &r->Link.hostname, r->Link.port, 0);
64
 
65
     // not doing IPv6 socks
66
     if (service.ss_family == AF_INET6)
67
obs-studio-0.16.6.tar.xz/plugins/obs-outputs/rtmp-stream.c -> obs-studio-0.17.0.tar.xz/plugins/obs-outputs/rtmp-stream.c Changed
71
 
1
@@ -134,7 +134,7 @@
2
    while (stream->packets.size) {
3
        struct encoder_packet packet;
4
        circlebuf_pop_front(&stream->packets, &packet, sizeof(packet));
5
-       obs_free_encoder_packet(&packet);
6
+       obs_encoder_packet_release(&packet);
7
    }
8
    pthread_mutex_unlock(&stream->packets_mutex);
9
 }
10
@@ -375,7 +375,10 @@
11
    ret = RTMP_Write(&stream->rtmp, (char*)data, (int)size, (int)idx);
12
    bfree(data);
13
 
14
-   obs_free_encoder_packet(packet);
15
+   if (is_header)
16
+       bfree(packet->data);
17
+   else
18
+       obs_encoder_packet_release(packet);
19
 
20
    stream->total_bytes_sent += size;
21
    return ret;
22
@@ -414,7 +417,7 @@
23
 
24
        if (stopping(stream)) {
25
            if (can_shutdown_stream(stream, &packet)) {
26
-               obs_free_encoder_packet(&packet);
27
+               obs_encoder_packet_release(&packet);
28
                break;
29
            }
30
        }
31
@@ -676,8 +679,10 @@
32
        bool success = netif_str_to_addr(&stream->rtmp.m_bindIP.addr,
33
                &stream->rtmp.m_bindIP.addrLen,
34
                stream->bind_ip.array);
35
-       if (success)
36
-           info("Binding to IP");
37
+       if (success) {
38
+           info("Binding to IPv%d", (stream->rtmp.m_bindIP.addrLen ==
39
+               sizeof(struct sockaddr_in6) ? 6 : 4));
40
+       }
41
    }
42
 
43
    RTMP_AddStream(&stream->rtmp, stream->key.array);
44
@@ -842,7 +847,7 @@
45
 
46
        } else {
47
            num_frames_dropped++;
48
-           obs_free_encoder_packet(&packet);
49
+           obs_encoder_packet_release(&packet);
50
        }
51
    }
52
 
53
@@ -927,7 +932,7 @@
54
    if (packet->type == OBS_ENCODER_VIDEO)
55
        obs_parse_avc_packet(&new_packet, packet);
56
    else
57
-       obs_duplicate_encoder_packet(&new_packet, packet);
58
+       obs_encoder_packet_ref(&new_packet, packet);
59
 
60
    pthread_mutex_lock(&stream->packets_mutex);
61
 
62
@@ -942,7 +947,7 @@
63
    if (added_packet)
64
        os_sem_post(stream->send_sem);
65
    else
66
-       obs_free_encoder_packet(&new_packet);
67
+       obs_encoder_packet_release(&new_packet);
68
 }
69
 
70
 static void rtmp_stream_defaults(obs_data_t *defaults)
71
obs-studio-0.16.6.tar.xz/plugins/obs-qsv11/CMakeLists.txt -> obs-studio-0.17.0.tar.xz/plugins/obs-qsv11/CMakeLists.txt Changed
33
 
1
@@ -48,9 +48,11 @@
2
    )
3
 
4
 set(obs-qsv11_SOURCES
5
+   common_directx9.cpp
6
    common_directx11.cpp
7
    common_utils.cpp
8
    common_utils_windows.cpp
9
+   device_directx9.cpp
10
    QSV_Encoder.cpp
11
    QSV_Encoder_Internal.cpp
12
    obs-qsv11.c
13
@@ -59,7 +61,9 @@
14
 set(obs-qsv11_HEADERS
15
    bits/linux_defs.h
16
    bits/windows_defs.h
17
+   common_directx9.h
18
    common_directx11.h
19
+   device_directx9.h
20
    common_utils.h
21
    QSV_Encoder.h
22
    QSV_Encoder_Internal.h)
23
@@ -72,7 +76,9 @@
24
    )
25
 target_link_libraries(obs-qsv11
26
    libobs
27
+   d3d9
28
    d3d11
29
+   dxva2
30
    dxgi
31
    )
32
 
33
obs-studio-0.16.6.tar.xz/plugins/obs-qsv11/QSV_Encoder_Internal.cpp -> obs-studio-0.17.0.tar.xz/plugins/obs-qsv11/QSV_Encoder_Internal.cpp Changed
115
 
1
@@ -83,6 +83,7 @@
2
 
3
    m_bIsWindows8OrGreater = IsWindows8OrGreater();
4
    m_bUseD3D11 = false;
5
+   m_bD3D9HACK = true;
6
 
7
    if (m_bIsWindows8OrGreater) {
8
        tempImpl = impl | MFX_IMPL_VIA_D3D11;
9
@@ -107,6 +108,21 @@
10
            return;
11
        }
12
    }
13
+   else if (m_bD3D9HACK) {
14
+       tempImpl = impl | MFX_IMPL_VIA_D3D9;
15
+       sts = m_session.Init(tempImpl, &version);
16
+       if (sts == MFX_ERR_NONE) {
17
+           m_session.QueryVersion(&version);
18
+           m_session.Close();
19
+
20
+           blog(LOG_INFO, "\timpl:           D3D09\n"
21
+                      "\tsurf:           Hack");
22
+
23
+           m_impl = tempImpl;
24
+           m_ver = version;
25
+           return;
26
+       }
27
+   }
28
 
29
    // Either windows 7 or D3D11 failed at this point.
30
    tempImpl = impl | MFX_IMPL_VIA_D3D9;
31
@@ -136,11 +152,14 @@
32
 
33
    if (m_bUseD3D11)
34
        // Use D3D11 surface
35
-       sts = Initialize(m_impl, m_ver, &m_session, &m_mfxAllocator);
36
+       sts = Initialize(m_impl, m_ver, &m_session, &m_mfxAllocator, false, false);
37
+   else if (m_bD3D9HACK)
38
+       // Use hack
39
+       sts = Initialize(m_impl, m_ver, &m_session, &m_mfxAllocator, false, true);
40
    else
41
-       // Use system memory
42
        sts = Initialize(m_impl, m_ver, &m_session, NULL);
43
 
44
+
45
    MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
46
 
47
    m_pmfxENC = new MFXVideoENCODE(m_session);
48
@@ -260,7 +279,7 @@
49
    m_mfxEncParams.mfx.FrameInfo.Width = MSDK_ALIGN16(pParams->nWidth);
50
    m_mfxEncParams.mfx.FrameInfo.Height = MSDK_ALIGN16(pParams->nHeight);
51
 
52
-   if (m_bUseD3D11)
53
+   if (m_bUseD3D11 || m_bD3D9HACK)
54
        m_mfxEncParams.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY;
55
    else
56
        m_mfxEncParams.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
57
@@ -282,7 +301,7 @@
58
    EncRequest.NumFrameSuggested += m_mfxEncParams.AsyncDepth;
59
 
60
    // Allocate required surfaces
61
-   if (m_bUseD3D11) {
62
+   if (m_bUseD3D11 || m_bD3D9HACK) {
63
        sts = m_mfxAllocator.Alloc(m_mfxAllocator.pthis, &EncRequest,
64
                &m_mfxResponse);
65
        MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
66
@@ -498,14 +517,14 @@
67
    }
68
 
69
    mfxFrameSurface1 *pSurface = m_pmfxSurfaces[nSurfIdx];
70
-   if (m_bUseD3D11)
71
+   if (m_bUseD3D11 || m_bD3D9HACK)
72
        sts = m_mfxAllocator.Lock(m_mfxAllocator.pthis,
73
                pSurface->Data.MemId, &(pSurface->Data));
74
 
75
    sts = LoadNV12(pSurface, pDataY, pDataUV, strideY, strideUV);
76
    pSurface->Data.TimeStamp = ts;
77
 
78
-   if (m_bUseD3D11)
79
+   if (m_bUseD3D11 || m_bD3D9HACK)
80
        sts = m_mfxAllocator.Unlock(m_mfxAllocator.pthis,
81
                pSurface->Data.MemId, &(pSurface->Data));
82
 
83
@@ -538,7 +557,7 @@
84
 {
85
    mfxStatus sts = MFX_ERR_NONE;
86
 
87
-   while (m_pTaskPool[m_nFirstSyncTask].syncp) {
88
+   while (m_pTaskPool && m_pTaskPool[m_nFirstSyncTask].syncp) {
89
        sts = m_session.SyncOperation(m_pTaskPool[m_nFirstSyncTask].syncp, 60000);
90
        MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
91
 
92
@@ -556,11 +575,11 @@
93
 
94
    sts = m_pmfxENC->Close();
95
 
96
-   if (m_bUseD3D11)
97
+   if (m_bUseD3D11 || m_bD3D9HACK)
98
        m_mfxAllocator.Free(m_mfxAllocator.pthis, &m_mfxResponse);
99
 
100
    for (int i = 0; i < m_nSurfNum; i++) {
101
-       if (!m_bUseD3D11)
102
+       if (!m_bUseD3D11 && !m_bD3D9HACK)
103
            delete m_pmfxSurfaces[i]->Data.Y;
104
 
105
        delete m_pmfxSurfaces[i];
106
@@ -578,7 +597,7 @@
107
        m_pmfxENC = NULL;
108
    }
109
 
110
-   if (m_bUseD3D11)
111
+   if (m_bUseD3D11 || m_bD3D9HACK)
112
        Release();
113
 
114
    m_session.Close();
115
obs-studio-0.16.6.tar.xz/plugins/obs-qsv11/QSV_Encoder_Internal.h -> obs-studio-0.17.0.tar.xz/plugins/obs-qsv11/QSV_Encoder_Internal.h Changed
8
 
1
@@ -108,5 +108,6 @@
2
    mfxBitstream                   m_outBitstream;
3
    bool                           m_bIsWindows8OrGreater;
4
    bool                           m_bUseD3D11;
5
+   bool                           m_bD3D9HACK;
6
 };
7
 
8
obs-studio-0.17.0.tar.xz/plugins/obs-qsv11/common_directx9.cpp Added
459
 
1
@@ -0,0 +1,457 @@
2
+#include "common_directx9.h"
3
+#include "device_directx9.h"
4
+
5
+#include <objbase.h>
6
+#include <initguid.h>
7
+#include <d3d9.h>
8
+#include <map>
9
+#include <atlbase.h>
10
+
11
+
12
+#define D3DFMT_NV12 (D3DFORMAT)MAKEFOURCC('N','V','1','2')
13
+#define D3DFMT_YV12 (D3DFORMAT)MAKEFOURCC('Y','V','1','2')
14
+#define D3DFMT_P010 (D3DFORMAT)MAKEFOURCC('P','0','1','0')
15
+#define MSDK_SAFE_FREE(X) {if (X) { free(X); X = NULL; }}
16
+
17
+std::map<mfxMemId*, mfxHDL>             dx9_allocResponses;
18
+std::map<mfxHDL, mfxFrameAllocResponse> dx9_allocDecodeResponses;
19
+std::map<mfxHDL, int>                   dx9_allocDecodeRefCount;
20
+
21
+CComPtr<IDirect3DDeviceManager9> m_manager;
22
+CComPtr<IDirectXVideoDecoderService> m_decoderService;
23
+CComPtr<IDirectXVideoProcessorService> m_processorService;
24
+HANDLE m_hDecoder;
25
+HANDLE m_hProcessor;
26
+DWORD m_surfaceUsage;
27
+
28
+CD3D9Device* g_hwdevice;
29
+
30
+const struct {
31
+   mfxIMPL impl;       // actual implementation
32
+   mfxU32  adapterID;  // device adapter number
33
+} implTypes[] = {
34
+   { MFX_IMPL_HARDWARE, 0 },
35
+   { MFX_IMPL_HARDWARE2, 1 },
36
+   { MFX_IMPL_HARDWARE3, 2 },
37
+   { MFX_IMPL_HARDWARE4, 3 }
38
+};
39
+
40
+struct mfxAllocatorParams
41
+{
42
+    virtual ~mfxAllocatorParams(){};
43
+};
44
+
45
+struct D3DAllocatorParams : mfxAllocatorParams
46
+{
47
+    IDirect3DDeviceManager9 *pManager;
48
+    DWORD surfaceUsage;
49
+
50
+    D3DAllocatorParams()
51
+        : pManager()
52
+        , surfaceUsage()
53
+    {
54
+    }
55
+};
56
+
57
+mfxStatus DX9_Alloc_Init(D3DAllocatorParams *pParams)
58
+{
59
+    D3DAllocatorParams *pd3dParams = 0;
60
+    pd3dParams = dynamic_cast<D3DAllocatorParams *>(pParams);
61
+    if (!pd3dParams)
62
+        return MFX_ERR_NOT_INITIALIZED;
63
+
64
+    m_manager = pd3dParams->pManager;
65
+    m_surfaceUsage = pd3dParams->surfaceUsage;
66
+
67
+    return MFX_ERR_NONE;
68
+}
69
+
70
+mfxStatus DX9_CreateHWDevice(mfxSession session, mfxHDL* deviceHandle, HWND, bool)
71
+{
72
+   mfxStatus result;
73
+
74
+   g_hwdevice = new CD3D9Device;
75
+   mfxU32  adapterNum = 0;
76
+   mfxIMPL impl;
77
+
78
+   MFXQueryIMPL(session, &impl);
79
+
80
+   mfxIMPL baseImpl = MFX_IMPL_BASETYPE(impl); // Extract Media SDK base implementation type
81
+
82
+                           // get corresponding adapter number
83
+   for (mfxU8 i = 0; i < sizeof(implTypes) / sizeof(implTypes[0]); i++) {
84
+       if (implTypes[i].impl == baseImpl) {
85
+           adapterNum = implTypes[i].adapterID;
86
+           break;
87
+       }
88
+   }
89
+
90
+   POINT point = { 0, 0 };
91
+   HWND window = WindowFromPoint(point);
92
+
93
+   result = g_hwdevice->Init(window, 0, adapterNum);
94
+   if (result != MFX_ERR_NONE) {
95
+       return result;
96
+   }
97
+
98
+   g_hwdevice->GetHandle(MFX_HANDLE_D3D9_DEVICE_MANAGER, deviceHandle);
99
+
100
+
101
+   D3DAllocatorParams dx9_allocParam;
102
+   dx9_allocParam.pManager = reinterpret_cast<IDirect3DDeviceManager9 *>(*deviceHandle);
103
+   DX9_Alloc_Init(&dx9_allocParam);
104
+   return MFX_ERR_NONE;
105
+}
106
+
107
+void DX9_CleanupHWDevice()
108
+{
109
+   if (g_hwdevice) {
110
+       // g_hwdevice->Close();
111
+       delete g_hwdevice;
112
+       g_hwdevice = NULL;
113
+   }
114
+   if (m_manager && m_hDecoder) {
115
+       m_manager->CloseDeviceHandle(m_hDecoder);
116
+       m_manager = NULL;
117
+       m_hDecoder = NULL;
118
+   }
119
+
120
+   if (m_manager && m_hProcessor) {
121
+       m_manager->CloseDeviceHandle(m_hProcessor);
122
+       m_manager = NULL;
123
+       m_hProcessor = NULL;
124
+   }
125
+
126
+   if (m_decoderService) {
127
+       // delete m_decoderService;
128
+       m_decoderService = NULL;
129
+   }
130
+
131
+   if (m_processorService) {
132
+       // delete m_processorService;
133
+       m_processorService = NULL;
134
+   }
135
+}
136
+
137
+D3DFORMAT ConvertMfxFourccToD3dFormat(mfxU32 fourcc)
138
+{
139
+   switch (fourcc)
140
+   {
141
+   case MFX_FOURCC_NV12:
142
+       return D3DFMT_NV12;
143
+   case MFX_FOURCC_YV12:
144
+       return D3DFMT_YV12;
145
+   case MFX_FOURCC_YUY2:
146
+       return D3DFMT_YUY2;
147
+   case MFX_FOURCC_RGB3:
148
+       return D3DFMT_R8G8B8;
149
+   case MFX_FOURCC_RGB4:
150
+       return D3DFMT_A8R8G8B8;
151
+   case MFX_FOURCC_P8:
152
+       return D3DFMT_P8;
153
+   case MFX_FOURCC_P010:
154
+       return D3DFMT_P010;
155
+   case MFX_FOURCC_A2RGB10:
156
+       return D3DFMT_A2R10G10B10;
157
+   default:
158
+       return D3DFMT_UNKNOWN;
159
+   }
160
+}
161
+
162
+mfxStatus dx9_simple_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData* ptr)
163
+{
164
+   pthis; // To suppress warning for this unused parameter
165
+
166
+   if (!ptr || !mid)
167
+       return MFX_ERR_NULL_PTR;
168
+
169
+   mfxHDLPair *dxmid = (mfxHDLPair*)mid;
170
+   IDirect3DSurface9 *pSurface = static_cast<IDirect3DSurface9*>(dxmid->first);
171
+   if (pSurface == 0)
172
+       return MFX_ERR_INVALID_HANDLE;
173
+
174
+   D3DSURFACE_DESC desc;
175
+   HRESULT hr = pSurface->GetDesc(&desc);
176
+   if (FAILED(hr))
177
+       return MFX_ERR_LOCK_MEMORY;
178
+
179
+   if (desc.Format != D3DFMT_NV12 &&
180
+       desc.Format != D3DFMT_YV12 &&
181
+       desc.Format != D3DFMT_YUY2 &&
182
+       desc.Format != D3DFMT_R8G8B8 &&
183
+       desc.Format != D3DFMT_A8R8G8B8 &&
184
+       desc.Format != D3DFMT_P8 &&
185
+       desc.Format != D3DFMT_P010 &&
186
+       desc.Format != D3DFMT_A2R10G10B10)
187
+       return MFX_ERR_LOCK_MEMORY;
188
+
189
+   D3DLOCKED_RECT locked;
190
+
191
+   hr = pSurface->LockRect(&locked, 0, D3DLOCK_NOSYSLOCK);
192
+   if (FAILED(hr))
193
+       return MFX_ERR_LOCK_MEMORY;
194
+
195
+   switch ((DWORD)desc.Format)
196
+   {
197
+   case D3DFMT_NV12:
198
+       ptr->Pitch = (mfxU16)locked.Pitch;
199
+       ptr->Y = (mfxU8 *)locked.pBits;
200
+       ptr->U = (mfxU8 *)locked.pBits + desc.Height * locked.Pitch;
201
+       ptr->V = ptr->U + 1;
202
+       break;
203
+   case D3DFMT_YV12:
204
+       ptr->Pitch = (mfxU16)locked.Pitch;
205
+       ptr->Y = (mfxU8 *)locked.pBits;
206
+       ptr->V = ptr->Y + desc.Height * locked.Pitch;
207
+       ptr->U = ptr->V + (desc.Height * locked.Pitch) / 4;
208
+       break;
209
+   case D3DFMT_YUY2:
210
+       ptr->Pitch = (mfxU16)locked.Pitch;
211
+       ptr->Y = (mfxU8 *)locked.pBits;
212
+       ptr->U = ptr->Y + 1;
213
+       ptr->V = ptr->Y + 3;
214
+       break;
215
+   case D3DFMT_R8G8B8:
216
+       ptr->Pitch = (mfxU16)locked.Pitch;
217
+       ptr->B = (mfxU8 *)locked.pBits;
218
+       ptr->G = ptr->B + 1;
219
+       ptr->R = ptr->B + 2;
220
+       break;
221
+   case D3DFMT_A8R8G8B8:
222
+   case D3DFMT_A2R10G10B10:
223
+       ptr->Pitch = (mfxU16)locked.Pitch;
224
+       ptr->B = (mfxU8 *)locked.pBits;
225
+       ptr->G = ptr->B + 1;
226
+       ptr->R = ptr->B + 2;
227
+       ptr->A = ptr->B + 3;
228
+       break;
229
+   case D3DFMT_P8:
230
+       ptr->Pitch = (mfxU16)locked.Pitch;
231
+       ptr->Y = (mfxU8 *)locked.pBits;
232
+       ptr->U = 0;
233
+       ptr->V = 0;
234
+       break;
235
+   case D3DFMT_P010:
236
+       ptr->PitchHigh = (mfxU16)(locked.Pitch / (1 << 16));
237
+       ptr->PitchLow = (mfxU16)(locked.Pitch % (1 << 16));
238
+       ptr->Y = (mfxU8 *)locked.pBits;
239
+       ptr->U = (mfxU8 *)locked.pBits + desc.Height * locked.Pitch;
240
+       ptr->V = ptr->U + 1;
241
+       break;
242
+   }
243
+
244
+   return MFX_ERR_NONE;
245
+}
246
+
247
+mfxStatus dx9_simple_unlock(mfxHDL, mfxMemId mid, mfxFrameData* ptr)
248
+{
249
+   if (!mid)
250
+       return MFX_ERR_NULL_PTR;
251
+
252
+   mfxHDLPair *dxmid = (mfxHDLPair*)mid;
253
+   IDirect3DSurface9 *pSurface = static_cast<IDirect3DSurface9*>(dxmid->first);
254
+   if (pSurface == 0)
255
+       return MFX_ERR_INVALID_HANDLE;
256
+
257
+   pSurface->UnlockRect();
258
+
259
+   if (NULL != ptr)
260
+   {
261
+       ptr->Pitch = 0;
262
+       ptr->Y = 0;
263
+       ptr->U = 0;
264
+       ptr->V = 0;
265
+   }
266
+
267
+   return MFX_ERR_NONE;
268
+}
269
+
270
+mfxStatus dx9_simple_gethdl(mfxHDL, mfxMemId mid, mfxHDL* handle)
271
+{
272
+   if (!mid || !handle)
273
+       return MFX_ERR_NULL_PTR;
274
+
275
+   mfxHDLPair *dxMid = (mfxHDLPair*)mid;
276
+   *handle = dxMid->first;
277
+   return MFX_ERR_NONE;
278
+}
279
+
280
+mfxStatus _dx9_simple_free(mfxFrameAllocResponse* response)
281
+{
282
+   if (!response)
283
+       return MFX_ERR_NULL_PTR;
284
+
285
+   mfxStatus sts = MFX_ERR_NONE;
286
+
287
+   if (response->mids) {
288
+       for (mfxU32 i = 0; i < response->NumFrameActual; i++) {
289
+           if (response->mids[i]) {
290
+               mfxHDLPair *dxMids = (mfxHDLPair*)response->mids[i];
291
+               static_cast<IDirect3DSurface9*>(dxMids->first)->Release();
292
+           }
293
+       }
294
+       MSDK_SAFE_FREE(response->mids[0]);
295
+   }
296
+   MSDK_SAFE_FREE(response->mids);
297
+
298
+   return sts;
299
+}
300
+
301
+mfxStatus dx9_simple_free(mfxHDL pthis, mfxFrameAllocResponse* response)
302
+{
303
+    if (NULL == response)
304
+        return MFX_ERR_NULL_PTR;
305
+
306
+    if (dx9_allocResponses.find(response->mids) == dx9_allocResponses.end()) {
307
+        // Decode free response handling
308
+        if (--dx9_allocDecodeRefCount[pthis] == 0) {
309
+            _dx9_simple_free(response);
310
+            dx9_allocDecodeResponses.erase(pthis);
311
+            dx9_allocDecodeRefCount.erase(pthis);
312
+        }
313
+    } else {
314
+        // Encode and VPP free response handling
315
+        dx9_allocResponses.erase(response->mids);
316
+        _dx9_simple_free(response);
317
+    }
318
+
319
+    return MFX_ERR_NONE;
320
+}
321
+
322
+mfxStatus _dx9_simple_alloc(mfxFrameAllocRequest* request, mfxFrameAllocResponse* response)
323
+{
324
+   HRESULT hr;
325
+
326
+   MSDK_CHECK_POINTER(request, MFX_ERR_NULL_PTR);
327
+   if (request->NumFrameSuggested == 0)
328
+       return MFX_ERR_UNKNOWN;
329
+
330
+   D3DFORMAT format = ConvertMfxFourccToD3dFormat(request->Info.FourCC);
331
+
332
+   if (format == D3DFMT_UNKNOWN)
333
+       return MFX_ERR_UNSUPPORTED;
334
+
335
+   DWORD   target;
336
+
337
+   if (MFX_MEMTYPE_DXVA2_DECODER_TARGET & request->Type)
338
+   {
339
+       target = DXVA2_VideoDecoderRenderTarget;
340
+   }
341
+   else if (MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET & request->Type)
342
+   {
343
+       target = DXVA2_VideoProcessorRenderTarget;
344
+   }
345
+   else
346
+       return MFX_ERR_UNSUPPORTED;
347
+
348
+   IDirectXVideoAccelerationService* videoService = NULL;
349
+
350
+   if (target == DXVA2_VideoProcessorRenderTarget) {
351
+       if (!m_hProcessor) {
352
+           hr = m_manager->OpenDeviceHandle(&m_hProcessor);
353
+           if (FAILED(hr))
354
+               return MFX_ERR_MEMORY_ALLOC;
355
+
356
+           hr = m_manager->GetVideoService(m_hProcessor, IID_IDirectXVideoProcessorService, (void**)&m_processorService);
357
+           if (FAILED(hr))
358
+               return MFX_ERR_MEMORY_ALLOC;
359
+       }
360
+       videoService = m_processorService;
361
+   }
362
+   else {
363
+       if (!m_hDecoder)
364
+       {
365
+           hr = m_manager->OpenDeviceHandle(&m_hDecoder);
366
+           if (FAILED(hr))
367
+               return MFX_ERR_MEMORY_ALLOC;
368
+
369
+           hr = m_manager->GetVideoService(m_hDecoder, IID_IDirectXVideoDecoderService, (void**)&m_decoderService);
370
+           if (FAILED(hr))
371
+               return MFX_ERR_MEMORY_ALLOC;
372
+       }
373
+       videoService = m_decoderService;
374
+   }
375
+
376
+   mfxHDLPair *dxMids = NULL, **dxMidPtrs = NULL;
377
+   dxMids = (mfxHDLPair*)calloc(request->NumFrameSuggested, sizeof(mfxHDLPair));
378
+   dxMidPtrs = (mfxHDLPair**)calloc(request->NumFrameSuggested, sizeof(mfxHDLPair*));
379
+
380
+   if (!dxMids || !dxMidPtrs) {
381
+       MSDK_SAFE_FREE(dxMids);
382
+       MSDK_SAFE_FREE(dxMidPtrs);
383
+       return MFX_ERR_MEMORY_ALLOC;
384
+   }
385
+
386
+   response->mids = (mfxMemId*)dxMidPtrs;
387
+   response->NumFrameActual = request->NumFrameSuggested;
388
+
389
+   if (request->Type & MFX_MEMTYPE_EXTERNAL_FRAME) {
390
+       for (int i = 0; i < request->NumFrameSuggested; i++) {
391
+           hr = videoService->CreateSurface(request->Info.Width, request->Info.Height, 0, format,
392
+               D3DPOOL_DEFAULT, m_surfaceUsage, target, (IDirect3DSurface9**)&dxMids[i].first, &dxMids[i].second);
393
+           if (FAILED(hr)) {
394
+               _dx9_simple_free(response);
395
+               MSDK_SAFE_FREE(dxMids);
396
+               return MFX_ERR_MEMORY_ALLOC;
397
+           }
398
+           dxMidPtrs[i] = &dxMids[i];
399
+       }
400
+   }
401
+   else {
402
+       safe_array<IDirect3DSurface9*> dxSrf(new IDirect3DSurface9*[request->NumFrameSuggested]);
403
+       if (!dxSrf.get())
404
+       {
405
+           MSDK_SAFE_FREE(dxMids);
406
+           return MFX_ERR_MEMORY_ALLOC;
407
+       }
408
+       hr = videoService->CreateSurface(request->Info.Width, request->Info.Height, request->NumFrameSuggested - 1, format,
409
+           D3DPOOL_DEFAULT, m_surfaceUsage, target, dxSrf.get(), NULL);
410
+       if (FAILED(hr))
411
+       {
412
+           MSDK_SAFE_FREE(dxMids);
413
+           return MFX_ERR_MEMORY_ALLOC;
414
+       }
415
+
416
+
417
+       for (int i = 0; i < request->NumFrameSuggested; i++) {
418
+           dxMids[i].first = dxSrf.get()[i];
419
+           dxMidPtrs[i] = &dxMids[i];
420
+       }
421
+   }
422
+   return MFX_ERR_NONE;
423
+}
424
+
425
+mfxStatus dx9_simple_alloc(mfxHDL pthis, mfxFrameAllocRequest* request, mfxFrameAllocResponse* response)
426
+{
427
+    mfxStatus sts = MFX_ERR_NONE;
428
+
429
+    if (request->Type & MFX_MEMTYPE_SYSTEM_MEMORY)
430
+        return MFX_ERR_UNSUPPORTED;
431
+
432
+    if (dx9_allocDecodeResponses.find(pthis) != dx9_allocDecodeResponses.end() &&
433
+        MFX_MEMTYPE_EXTERNAL_FRAME & request->Type &&
434
+        MFX_MEMTYPE_FROM_DECODE & request->Type) {
435
+        // Memory for this request was already allocated during manual allocation stage. Return saved response
436
+        //   When decode acceleration device (DXVA) is created it requires a list of d3d surfaces to be passed.
437
+        //   Therefore Media SDK will ask for the surface info/mids again at Init() stage, thus requiring us to return the saved response
438
+        //   (No such restriction applies to Encode or VPP)
439
+        *response = dx9_allocDecodeResponses[pthis];
440
+        dx9_allocDecodeRefCount[pthis]++;
441
+    } else {
442
+        sts = _dx9_simple_alloc(request, response);
443
+
444
+        if (MFX_ERR_NONE == sts) {
445
+            if ( MFX_MEMTYPE_EXTERNAL_FRAME & request->Type &&
446
+                 MFX_MEMTYPE_FROM_DECODE & request->Type) {
447
+                // Decode alloc response handling
448
+                dx9_allocDecodeResponses[pthis] = *response;
449
+                dx9_allocDecodeRefCount[pthis]++;
450
+            } else {
451
+                // Encode and VPP alloc response handling
452
+                dx9_allocResponses[response->mids] = pthis;
453
+            }
454
+        }
455
+    }
456
+
457
+    return sts;
458
+}
459
obs-studio-0.17.0.tar.xz/plugins/obs-qsv11/common_directx9.h Added
72
 
1
@@ -0,0 +1,70 @@
2
+/*********************************************************************************
3
+
4
+INTEL CORPORATION PROPRIETARY INFORMATION
5
+This software is supplied under the terms of a license agreement or nondisclosure
6
+agreement with Intel Corporation and may not be copied or disclosed except in
7
+accordance with the terms of that agreement
8
+Copyright(c) 2011-2014 Intel Corporation. All Rights Reserved.
9
+
10
+**********************************************************************************/
11
+
12
+#pragma once
13
+
14
+#include "common_utils.h"
15
+#include <initguid.h>
16
+#include <d3d9.h>
17
+#include <dxva2api.h>
18
+#include <dxva.h>
19
+#include <windows.h>
20
+
21
+#define VIDEO_MAIN_FORMAT D3DFMT_YUY2
22
+
23
+class IGFXS3DControl;
24
+
25
+/** Direct3D 9 device implementation.
26
+@note Can be initilized for only 1 or two 2 views. Handle to
27
+MFX_HANDLE_GFXS3DCONTROL must be set prior if initializing for 2 views.
28
+
29
+@note Device always set D3DPRESENT_PARAMETERS::Windowed to TRUE.
30
+*/
31
+    template <class T>
32
+    class safe_array
33
+    {
34
+    public:
35
+        safe_array(T *ptr = 0):m_ptr(ptr)
36
+        { // construct from object pointer
37
+        };
38
+        ~safe_array()
39
+        {
40
+            reset(0);
41
+        }
42
+        T* get()
43
+        { // return wrapped pointer
44
+            return m_ptr;
45
+        }
46
+        T* release()
47
+        { // return wrapped pointer and give up ownership
48
+            T* ptr = m_ptr;
49
+            m_ptr = 0;
50
+            return ptr;
51
+        }
52
+        void reset(T* ptr)
53
+        { // destroy designated object and store new pointer
54
+            if (m_ptr)
55
+            {
56
+                delete[] m_ptr;
57
+            }
58
+            m_ptr = ptr;
59
+        }
60
+    protected:
61
+        T* m_ptr; // the wrapped object pointer
62
+    };
63
+
64
+mfxStatus dx9_simple_alloc(mfxHDL pthis, mfxFrameAllocRequest* request, mfxFrameAllocResponse* response);
65
+mfxStatus dx9_simple_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData* ptr);
66
+mfxStatus dx9_simple_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData* ptr);
67
+mfxStatus dx9_simple_gethdl(mfxHDL pthis, mfxMemId mid, mfxHDL* handle);
68
+mfxStatus dx9_simple_free(mfxHDL pthis, mfxFrameAllocResponse* response);
69
+
70
+mfxStatus DX9_CreateHWDevice(mfxSession session, mfxHDL* deviceHandle, HWND hWnd, bool bCreateSharedHandles);
71
+void DX9_CleanupHWDevice();
72
obs-studio-0.16.6.tar.xz/plugins/obs-qsv11/common_utils.h -> obs-studio-0.17.0.tar.xz/plugins/obs-qsv11/common_utils.h Changed
10
 
1
@@ -95,7 +95,7 @@
2
 int GetFreeTaskIndex(Task* pTaskPool, mfxU16 nPoolSize);
3
 
4
 // Initialize Intel Media SDK Session, device/display and memory manager
5
-mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mfxFrameAllocator* pmfxAllocator, bool bCreateSharedHandles = false);
6
+mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mfxFrameAllocator* pmfxAllocator, bool bCreateSharedHandles = false, bool dx9hack = false);
7
 
8
 // Release resources (device/display)
9
 void Release();
10
obs-studio-0.16.6.tar.xz/plugins/obs-qsv11/common_utils_windows.cpp -> obs-studio-0.17.0.tar.xz/plugins/obs-qsv11/common_utils_windows.cpp Changed
84
 
1
@@ -16,13 +16,14 @@
2
 #include "common_directx.h"
3
 #elif DX11_D3D
4
 #include "common_directx11.h"
5
+#include "common_directx9.h"
6
 #endif
7
 
8
 /* =======================================================
9
  * Windows implementation of OS-specific utility functions
10
  */
11
 
12
-mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mfxFrameAllocator* pmfxAllocator, bool bCreateSharedHandles)
13
+mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mfxFrameAllocator* pmfxAllocator, bool bCreateSharedHandles, bool dx9hack)
14
 {
15
     bCreateSharedHandles; // (Hugh) Currently unused
16
     pmfxAllocator; // (Hugh) Currently unused
17
@@ -30,10 +31,10 @@
18
     mfxStatus sts = MFX_ERR_NONE;
19
 
20
     // If mfxFrameAllocator is provided it means we need to setup DirectX device and memory allocator
21
-    if (pmfxAllocator) {
22
-       // Initialize Intel Media SDK Session
23
-       sts = pSession->Init(impl, &ver);
24
-       MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
25
+    if (pmfxAllocator && !dx9hack) {
26
+        // Initialize Intel Media SDK Session
27
+        sts = pSession->Init(impl, &ver);
28
+        MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
29
 
30
         // Create DirectX device context
31
         mfxHDL deviceHandle;
32
@@ -54,13 +55,37 @@
33
         // Since we are using video memory we must provide Media SDK with an external allocator
34
         sts = pSession->SetFrameAllocator(pmfxAllocator);
35
         MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
36
+
37
+    } else if (pmfxAllocator && dx9hack) {
38
+        // Initialize Intel Media SDK Session
39
+        sts = pSession->Init(impl, &ver);
40
+        MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
41
+
42
+        // Create DirectX device context
43
+        mfxHDL deviceHandle;
44
+        sts = DX9_CreateHWDevice(*pSession, &deviceHandle, NULL, bCreateSharedHandles);
45
+        MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
46
+
47
+        // Provide device manager to Media SDK
48
+        sts = pSession->SetHandle(MFX_HANDLE_D3D9_DEVICE_MANAGER, deviceHandle);
49
+        MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
50
+
51
+        pmfxAllocator->pthis  = *pSession; // We use Media SDK session ID as the allocation identifier
52
+        pmfxAllocator->Alloc  = dx9_simple_alloc;
53
+        pmfxAllocator->Free   = dx9_simple_free;
54
+        pmfxAllocator->Lock   = dx9_simple_lock;
55
+        pmfxAllocator->Unlock = dx9_simple_unlock;
56
+        pmfxAllocator->GetHDL = dx9_simple_gethdl;
57
+
58
+        // Since we are using video memory we must provide Media SDK with an external allocator
59
+        sts = pSession->SetFrameAllocator(pmfxAllocator);
60
+        MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
61
+
62
+    } else {
63
+        // Initialize Intel Media SDK Session
64
+        sts = pSession->Init(impl, &ver);
65
+        MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
66
     }
67
-   else
68
-   {
69
-       // Initialize Intel Media SDK Session
70
-       sts = pSession->Init(impl, &ver);
71
-       MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
72
-   }
73
     return sts;
74
 }
75
 
76
@@ -68,6 +93,7 @@
77
 {
78
 #if defined(DX9_D3D) || defined(DX11_D3D)
79
     CleanupHWDevice();
80
+    DX9_CleanupHWDevice();
81
 #endif
82
 }
83
 
84
obs-studio-0.17.0.tar.xz/plugins/obs-qsv11/data/locale/da-DK.ini Added
14
 
1
@@ -0,0 +1,12 @@
2
+TargetUsage="TargetUsage"
3
+Bitrate="Bithastighed"
4
+MaxBitrate="Maks. bithastighed"
5
+RateControl="Hastighedskontrol"
6
+KeyframeIntervalSec="Keyframe-interval (sek., 0= auto)"
7
+Profile="Profil"
8
+AsyncDepth="Asynk. dybde"
9
+Accuracy="Nøjagtighed"
10
+Convergence="Konvergens"
11
+ICQQuality="ICQ-kvalitet"
12
+LookAheadDepth="Lookahead-dybde"
13
+
14
obs-studio-0.16.6.tar.xz/plugins/obs-qsv11/data/locale/tr-TR.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-qsv11/data/locale/tr-TR.ini Changed
10
 
1
@@ -1,6 +1,8 @@
2
+TargetUsage="Hedef Kullanımı"
3
 Bitrate="Bit hızı"
4
 MaxBitrate="Maks Bit hızı"
5
 KeyframeIntervalSec="Anahtarkare Aralığı (saniye, 0=otomatik)"
6
 Profile="Profil"
7
 Accuracy="Doğruluk"
8
+ICQQuality="ICQ Kalitesi"
9
 
10
obs-studio-0.17.0.tar.xz/plugins/obs-qsv11/device_directx9.cpp Added
454
 
1
@@ -0,0 +1,451 @@
2
+/*********************************************************************************
3
+
4
+INTEL CORPORATION PROPRIETARY INFORMATION
5
+This software is supplied under the terms of a license agreement or nondisclosure
6
+agreement with Intel Corporation and may not be copied or disclosed except in
7
+accordance with the terms of that agreement
8
+Copyright(c) 2011-2015 Intel Corporation. All Rights Reserved.
9
+
10
+**********************************************************************************/
11
+
12
+// #include "mfx_samples_config.h"
13
+
14
+#if defined(WIN32) || defined(WIN64)
15
+
16
+//prefast singnature used in combaseapi.h
17
+#ifndef _PREFAST_
18
+    #pragma warning(disable:4068)
19
+#endif
20
+
21
+#include "device_directx9.h"
22
+// #include "igfx_s3dcontrol.h"
23
+
24
+#include "atlbase.h"
25
+
26
+// Macros
27
+#define MSDK_ZERO_MEMORY(VAR)                    {memset(&VAR, 0, sizeof(VAR));}
28
+#define MSDK_MEMCPY_VAR(dstVarName, src, count) memcpy_s(&(dstVarName), sizeof(dstVarName), (src), (count))
29
+
30
+CD3D9Device::CD3D9Device()
31
+{
32
+    m_pD3D9 = NULL;
33
+    m_pD3DD9 = NULL;
34
+    m_pDeviceManager9 = NULL;
35
+    MSDK_ZERO_MEMORY(m_D3DPP);
36
+    m_resetToken = 0;
37
+
38
+    m_nViews = 0;
39
+    m_pS3DControl = NULL;
40
+
41
+    MSDK_ZERO_MEMORY(m_backBufferDesc);
42
+    m_pDXVAVPS = NULL;
43
+    m_pDXVAVP_Left = NULL;
44
+    m_pDXVAVP_Right = NULL;
45
+
46
+    MSDK_ZERO_MEMORY(m_targetRect);
47
+
48
+    MSDK_ZERO_MEMORY(m_VideoDesc);
49
+    MSDK_ZERO_MEMORY(m_BltParams);
50
+    MSDK_ZERO_MEMORY(m_Sample);
51
+
52
+    // Initialize DXVA structures
53
+
54
+    DXVA2_AYUVSample16 color = {
55
+        0x8000,          // Cr
56
+        0x8000,          // Cb
57
+        0x1000,          // Y
58
+        0xffff           // Alpha
59
+    };
60
+
61
+    DXVA2_ExtendedFormat format =   {           // DestFormat
62
+        DXVA2_SampleProgressiveFrame,           // SampleFormat
63
+        DXVA2_VideoChromaSubsampling_MPEG2,     // VideoChromaSubsampling
64
+        DXVA_NominalRange_0_255,                // NominalRange
65
+        DXVA2_VideoTransferMatrix_BT709,        // VideoTransferMatrix
66
+        DXVA2_VideoLighting_bright,             // VideoLighting
67
+        DXVA2_VideoPrimaries_BT709,             // VideoPrimaries
68
+        DXVA2_VideoTransFunc_709                // VideoTransferFunction
69
+    };
70
+
71
+    // init m_VideoDesc structure
72
+    MSDK_MEMCPY_VAR(m_VideoDesc.SampleFormat, &format, sizeof(DXVA2_ExtendedFormat));
73
+    m_VideoDesc.SampleWidth                         = 0;
74
+    m_VideoDesc.SampleHeight                        = 0;
75
+    m_VideoDesc.InputSampleFreq.Numerator           = 60;
76
+    m_VideoDesc.InputSampleFreq.Denominator         = 1;
77
+    m_VideoDesc.OutputFrameFreq.Numerator           = 60;
78
+    m_VideoDesc.OutputFrameFreq.Denominator         = 1;
79
+
80
+    // init m_BltParams structure
81
+    MSDK_MEMCPY_VAR(m_BltParams.DestFormat, &format, sizeof(DXVA2_ExtendedFormat));
82
+    MSDK_MEMCPY_VAR(m_BltParams.BackgroundColor, &color, sizeof(DXVA2_AYUVSample16));
83
+
84
+    // init m_Sample structure
85
+    m_Sample.Start = 0;
86
+    m_Sample.End = 1;
87
+    m_Sample.SampleFormat = format;
88
+    m_Sample.PlanarAlpha.Fraction = 0;
89
+    m_Sample.PlanarAlpha.Value = 1;
90
+
91
+    m_bIsA2rgb10 = FALSE;
92
+}
93
+
94
+bool CD3D9Device::CheckOverlaySupport()
95
+{
96
+    D3DCAPS9                d3d9caps;
97
+    D3DOVERLAYCAPS          d3doverlaycaps = {0};
98
+    IDirect3D9ExOverlayExtension *d3d9overlay = NULL;
99
+    bool overlaySupported = false;
100
+
101
+    memset(&d3d9caps, 0, sizeof(d3d9caps));
102
+    HRESULT hr = m_pD3D9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3d9caps);
103
+    if (FAILED(hr) || !(d3d9caps.Caps & D3DCAPS_OVERLAY))
104
+    {
105
+        overlaySupported = false;
106
+    }
107
+    else
108
+    {
109
+        hr = m_pD3D9->QueryInterface(IID_PPV_ARGS(&d3d9overlay));
110
+        if (FAILED(hr) || (d3d9overlay == NULL))
111
+        {
112
+            overlaySupported = false;
113
+        }
114
+        else
115
+        {
116
+            hr = d3d9overlay->CheckDeviceOverlayType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
117
+                m_D3DPP.BackBufferWidth,
118
+                m_D3DPP.BackBufferHeight,
119
+                m_D3DPP.BackBufferFormat, NULL,
120
+                D3DDISPLAYROTATION_IDENTITY, &d3doverlaycaps);
121
+            MSDK_SAFE_RELEASE(d3d9overlay);
122
+
123
+            if (FAILED(hr))
124
+            {
125
+                overlaySupported = false;
126
+            }
127
+            else
128
+            {
129
+                overlaySupported = true;
130
+            }
131
+        }
132
+    }
133
+
134
+    return overlaySupported;
135
+}
136
+
137
+mfxStatus CD3D9Device::FillD3DPP(mfxHDL hWindow, mfxU16 nViews, D3DPRESENT_PARAMETERS &D3DPP)
138
+{
139
+    mfxStatus sts = MFX_ERR_NONE;
140
+
141
+    D3DPP.Windowed = true;
142
+    D3DPP.hDeviceWindow = (HWND)hWindow;
143
+
144
+    D3DPP.Flags                      = D3DPRESENTFLAG_VIDEO;
145
+    D3DPP.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
146
+    D3DPP.PresentationInterval       = D3DPRESENT_INTERVAL_ONE; // note that this setting leads to an implicit timeBeginPeriod call
147
+    D3DPP.BackBufferCount            = 1;
148
+    D3DPP.BackBufferFormat           = (m_bIsA2rgb10) ? D3DFMT_A2R10G10B10 : D3DFMT_X8R8G8B8;
149
+
150
+    if (hWindow)
151
+    {
152
+        RECT r;
153
+        GetClientRect((HWND)hWindow, &r);
154
+        int x = GetSystemMetrics(SM_CXSCREEN);
155
+        int y = GetSystemMetrics(SM_CYSCREEN);
156
+        D3DPP.BackBufferWidth  = min(r.right - r.left, x);
157
+        D3DPP.BackBufferHeight = min(r.bottom - r.top, y);
158
+    }
159
+    else
160
+    {
161
+        D3DPP.BackBufferWidth  = GetSystemMetrics(SM_CYSCREEN);
162
+        D3DPP.BackBufferHeight = GetSystemMetrics(SM_CYSCREEN);
163
+    }
164
+    //
165
+    // Mark the back buffer lockable if software DXVA2 could be used.
166
+    // This is because software DXVA2 device requires a lockable render target
167
+    // for the optimal performance.
168
+    //
169
+    {
170
+        D3DPP.Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
171
+    }
172
+
173
+    bool isOverlaySupported = CheckOverlaySupport();
174
+    if (2 == nViews && !isOverlaySupported)
175
+        return MFX_ERR_UNSUPPORTED;
176
+
177
+    bool needOverlay = (2 == nViews) ? true : false;
178
+
179
+    D3DPP.SwapEffect = needOverlay ? D3DSWAPEFFECT_OVERLAY : D3DSWAPEFFECT_DISCARD;
180
+
181
+    return sts;
182
+}
183
+
184
+mfxStatus CD3D9Device::Init(
185
+    mfxHDL hWindow,
186
+    mfxU16 nViews,
187
+    mfxU32 nAdapterNum)
188
+{
189
+    mfxStatus sts = MFX_ERR_NONE;
190
+
191
+    if (2 < nViews)
192
+        return MFX_ERR_UNSUPPORTED;
193
+
194
+    m_nViews = nViews;
195
+
196
+    HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &m_pD3D9);
197
+    if (!m_pD3D9 || FAILED(hr))
198
+        return MFX_ERR_DEVICE_FAILED;
199
+
200
+    ZeroMemory(&m_D3DPP, sizeof(m_D3DPP));
201
+    sts = FillD3DPP(hWindow, nViews, m_D3DPP);
202
+    MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
203
+
204
+    hr = m_pD3D9->CreateDeviceEx(
205
+        nAdapterNum,
206
+        D3DDEVTYPE_HAL,
207
+        (HWND)hWindow,
208
+        D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
209
+        &m_D3DPP,
210
+        NULL,
211
+        &m_pD3DD9);
212
+    if (FAILED(hr))
213
+        return MFX_ERR_NULL_PTR;
214
+
215
+    if(hWindow)
216
+    {
217
+        hr = m_pD3DD9->ResetEx(&m_D3DPP, NULL);
218
+        if (FAILED(hr))
219
+            return MFX_ERR_UNDEFINED_BEHAVIOR;
220
+        hr = m_pD3DD9->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
221
+        if (FAILED(hr))
222
+            return MFX_ERR_UNDEFINED_BEHAVIOR;
223
+    }
224
+    UINT resetToken = 0;
225
+
226
+    hr = DXVA2CreateDirect3DDeviceManager9(&resetToken, &m_pDeviceManager9);
227
+    if (FAILED(hr))
228
+        return MFX_ERR_NULL_PTR;
229
+
230
+    hr = m_pDeviceManager9->ResetDevice(m_pD3DD9, resetToken);
231
+    if (FAILED(hr))
232
+        return MFX_ERR_UNDEFINED_BEHAVIOR;
233
+
234
+    m_resetToken = resetToken;
235
+
236
+    return sts;
237
+}
238
+
239
+mfxStatus CD3D9Device::Reset()
240
+{
241
+    HRESULT hr = NO_ERROR;
242
+    MSDK_CHECK_POINTER(m_pD3DD9, MFX_ERR_NULL_PTR);
243
+
244
+    if (m_D3DPP.Windowed)
245
+    {
246
+        RECT r;
247
+        GetClientRect((HWND)m_D3DPP.hDeviceWindow, &r);
248
+        int x = GetSystemMetrics(SM_CXSCREEN);
249
+        int y = GetSystemMetrics(SM_CYSCREEN);
250
+        m_D3DPP.BackBufferWidth  = min(r.right - r.left, x);
251
+        m_D3DPP.BackBufferHeight = min(r.bottom - r.top, y);
252
+    }
253
+    else
254
+    {
255
+        m_D3DPP.BackBufferWidth  = GetSystemMetrics(SM_CXSCREEN);
256
+        m_D3DPP.BackBufferHeight = GetSystemMetrics(SM_CYSCREEN);
257
+    }
258
+
259
+    // Reset will change the parameters, so use a copy instead.
260
+    D3DPRESENT_PARAMETERS d3dpp = m_D3DPP;
261
+    hr = m_pD3DD9->ResetEx(&d3dpp, NULL);
262
+
263
+    if (FAILED(hr))
264
+        return MFX_ERR_UNDEFINED_BEHAVIOR;
265
+
266
+    hr = m_pDeviceManager9->ResetDevice(m_pD3DD9, m_resetToken);
267
+    if (FAILED(hr))
268
+        return MFX_ERR_UNDEFINED_BEHAVIOR;
269
+
270
+    return MFX_ERR_NONE;
271
+}
272
+
273
+void CD3D9Device::Close()
274
+{
275
+    MSDK_SAFE_RELEASE(m_pDXVAVP_Left);
276
+    MSDK_SAFE_RELEASE(m_pDXVAVP_Right);
277
+    MSDK_SAFE_RELEASE(m_pDXVAVPS);
278
+
279
+    MSDK_SAFE_RELEASE(m_pDeviceManager9);
280
+    MSDK_SAFE_RELEASE(m_pD3DD9);
281
+    MSDK_SAFE_RELEASE(m_pD3D9);
282
+    m_pS3DControl = NULL;
283
+}
284
+
285
+CD3D9Device::~CD3D9Device()
286
+{
287
+    Close();
288
+}
289
+
290
+mfxStatus CD3D9Device::GetHandle(mfxHandleType type, mfxHDL *pHdl)
291
+{
292
+    if (MFX_HANDLE_DIRECT3D_DEVICE_MANAGER9 == type && pHdl != NULL)
293
+    {
294
+        *pHdl = m_pDeviceManager9;
295
+
296
+        return MFX_ERR_NONE;
297
+    }
298
+    else if (MFX_HANDLE_GFXS3DCONTROL == type && pHdl != NULL)
299
+    {
300
+        *pHdl = m_pS3DControl;
301
+
302
+        return MFX_ERR_NONE;
303
+    }
304
+    return MFX_ERR_UNSUPPORTED;
305
+}
306
+
307
+mfxStatus CD3D9Device::SetHandle(mfxHandleType type, mfxHDL hdl)
308
+{
309
+    if (MFX_HANDLE_GFXS3DCONTROL == type && hdl != NULL)
310
+    {
311
+        m_pS3DControl = (IGFXS3DControl*)hdl;
312
+        return MFX_ERR_NONE;
313
+    }
314
+    else if (MFX_HANDLE_DEVICEWINDOW == type && hdl != NULL) //for render window handle
315
+    {
316
+        m_D3DPP.hDeviceWindow = (HWND)hdl;
317
+        return MFX_ERR_NONE;
318
+    }
319
+    return MFX_ERR_UNSUPPORTED;
320
+}
321
+
322
+mfxStatus CD3D9Device::RenderFrame(mfxFrameSurface1 * pSurface, mfxFrameAllocator * pmfxAlloc)
323
+{
324
+    HRESULT hr = S_OK;
325
+
326
+    if (!(1 == m_nViews || (2 == m_nViews && NULL != m_pS3DControl)))
327
+        return MFX_ERR_UNDEFINED_BEHAVIOR;
328
+
329
+    MSDK_CHECK_POINTER(pSurface, MFX_ERR_NULL_PTR);
330
+    MSDK_CHECK_POINTER(m_pDeviceManager9, MFX_ERR_NOT_INITIALIZED);
331
+    MSDK_CHECK_POINTER(pmfxAlloc, MFX_ERR_NULL_PTR);
332
+
333
+    // don't try to render second view if output rect changed since first view
334
+    if (2 == m_nViews && (0 != pSurface->Info.FrameId.ViewId))
335
+        return MFX_ERR_NONE;
336
+
337
+    hr = m_pD3DD9->TestCooperativeLevel();
338
+
339
+    switch (hr)
340
+    {
341
+        case D3D_OK :
342
+            break;
343
+
344
+        case D3DERR_DEVICELOST :
345
+        {
346
+            return MFX_ERR_DEVICE_LOST;
347
+        }
348
+
349
+        case D3DERR_DEVICENOTRESET :
350
+            {
351
+            return MFX_ERR_UNKNOWN;
352
+        }
353
+
354
+        default :
355
+        {
356
+            return MFX_ERR_UNKNOWN;
357
+        }
358
+    }
359
+
360
+    CComPtr<IDirect3DSurface9> pBackBuffer;
361
+    hr = m_pD3DD9->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
362
+
363
+    mfxHDLPair* dxMemId = (mfxHDLPair*)pSurface->Data.MemId;
364
+
365
+    hr = m_pD3DD9->StretchRect((IDirect3DSurface9*)dxMemId->first, NULL, pBackBuffer, NULL, D3DTEXF_LINEAR);
366
+    if (FAILED(hr))
367
+    {
368
+        return MFX_ERR_UNKNOWN;
369
+    }
370
+
371
+    if (SUCCEEDED(hr)&& (1 == m_nViews || pSurface->Info.FrameId.ViewId == 1))
372
+    {
373
+        hr = m_pD3DD9->Present(NULL, NULL, NULL, NULL);
374
+    }
375
+
376
+    return SUCCEEDED(hr) ? MFX_ERR_NONE : MFX_ERR_DEVICE_FAILED;
377
+}
378
+
379
+/*
380
+mfxStatus CD3D9Device::CreateVideoProcessors()
381
+{
382
+    if (!(1 == m_nViews || (2 == m_nViews && NULL != m_pS3DControl)))
383
+        return MFX_ERR_UNDEFINED_BEHAVIOR;
384
+
385
+   MSDK_SAFE_RELEASE(m_pDXVAVP_Left);
386
+   MSDK_SAFE_RELEASE(m_pDXVAVP_Right);
387
+
388
+   HRESULT hr ;
389
+
390
+   if (2 == m_nViews && NULL != m_pS3DControl)
391
+   {
392
+       hr = m_pS3DControl->SetDevice(m_pDeviceManager9);
393
+       if (FAILED(hr))
394
+       {
395
+           return MFX_ERR_DEVICE_FAILED;
396
+       }
397
+   }
398
+
399
+   ZeroMemory(&m_backBufferDesc, sizeof(m_backBufferDesc));
400
+   IDirect3DSurface9 *backBufferTmp = NULL;
401
+   hr = m_pD3DD9->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBufferTmp);
402
+   if (NULL != backBufferTmp)
403
+       backBufferTmp->GetDesc(&m_backBufferDesc);
404
+   MSDK_SAFE_RELEASE(backBufferTmp);
405
+
406
+   if (SUCCEEDED(hr))
407
+   {
408
+       // Create DXVA2 Video Processor Service.
409
+       hr = DXVA2CreateVideoService(m_pD3DD9,
410
+           IID_IDirectXVideoProcessorService,
411
+           (void**)&m_pDXVAVPS);
412
+   }
413
+
414
+   if (2 == m_nViews)
415
+   {
416
+        // Activate L channel
417
+        if (SUCCEEDED(hr))
418
+        {
419
+           hr = m_pS3DControl->SelectLeftView();
420
+        }
421
+
422
+        if (SUCCEEDED(hr))
423
+        {
424
+           // Create VPP device for the L channel
425
+           hr = m_pDXVAVPS->CreateVideoProcessor(DXVA2_VideoProcProgressiveDevice,
426
+               &m_VideoDesc,
427
+               m_D3DPP.BackBufferFormat,
428
+               1,
429
+               &m_pDXVAVP_Left);
430
+        }
431
+
432
+        // Activate R channel
433
+        if (SUCCEEDED(hr))
434
+        {
435
+           hr = m_pS3DControl->SelectRightView();
436
+        }
437
+
438
+   }
439
+   if (SUCCEEDED(hr))
440
+   {
441
+       hr = m_pDXVAVPS->CreateVideoProcessor(DXVA2_VideoProcProgressiveDevice,
442
+           &m_VideoDesc,
443
+           m_D3DPP.BackBufferFormat,
444
+           1,
445
+           &m_pDXVAVP_Right);
446
+   }
447
+
448
+   return SUCCEEDED(hr) ? MFX_ERR_NONE : MFX_ERR_DEVICE_FAILED;
449
+}
450
+*/
451
+
452
+#endif // #if defined(WIN32) || defined(WIN64)
453
\ No newline at end of file
454
obs-studio-0.17.0.tar.xz/plugins/obs-qsv11/device_directx9.h Added
121
 
1
@@ -0,0 +1,118 @@
2
+/*********************************************************************************
3
+
4
+INTEL CORPORATION PROPRIETARY INFORMATION
5
+This software is supplied under the terms of a license agreement or nondisclosure
6
+agreement with Intel Corporation and may not be copied or disclosed except in
7
+accordance with the terms of that agreement
8
+Copyright(c) 2011-2014 Intel Corporation. All Rights Reserved.
9
+
10
+**********************************************************************************/
11
+
12
+#pragma once
13
+
14
+#if defined( _WIN32 ) || defined ( _WIN64 )
15
+
16
+#include "common_utils.h"
17
+
18
+#pragma warning(disable : 4201)
19
+#include <initguid.h>
20
+#include <d3d9.h>
21
+#include <dxva2api.h>
22
+#include <dxva.h>
23
+#include <windows.h>
24
+
25
+#define VIDEO_MAIN_FORMAT D3DFMT_YUY2
26
+
27
+class IGFXS3DControl;
28
+
29
+
30
+/// Base class for hw device
31
+class CHWDevice
32
+{
33
+public:
34
+    virtual ~CHWDevice(){}
35
+    /** Initializes device for requested processing.
36
+    @param[in] hWindow Window handle to bundle device to.
37
+    @param[in] nViews Number of views to process.
38
+    @param[in] nAdapterNum Number of adapter to use
39
+    */
40
+    virtual mfxStatus Init(
41
+        mfxHDL hWindow,
42
+        mfxU16 nViews,
43
+        mfxU32 nAdapterNum) = 0;
44
+    /// Reset device.
45
+    virtual mfxStatus Reset() = 0;
46
+    /// Get handle can be used for MFX session SetHandle calls
47
+    virtual mfxStatus GetHandle(mfxHandleType type, mfxHDL *pHdl) = 0;
48
+    /** Set handle.
49
+    Particular device implementation may require other objects to operate.
50
+    */
51
+    virtual mfxStatus SetHandle(mfxHandleType type, mfxHDL hdl) = 0;
52
+    virtual mfxStatus RenderFrame(mfxFrameSurface1 * pSurface, mfxFrameAllocator * pmfxAlloc) = 0;
53
+    virtual void      Close() = 0;
54
+};
55
+
56
+enum {
57
+    MFX_HANDLE_GFXS3DCONTROL = 0x100, /* A handle to the IGFXS3DControl instance */
58
+    MFX_HANDLE_DEVICEWINDOW  = 0x101 /* A handle to the render window */
59
+}; //mfxHandleType
60
+
61
+/** Direct3D 9 device implementation.
62
+@note Can be initilized for only 1 or two 2 views. Handle to
63
+MFX_HANDLE_GFXS3DCONTROL must be set prior if initializing for 2 views.
64
+
65
+@note Device always set D3DPRESENT_PARAMETERS::Windowed to TRUE.
66
+*/
67
+class CD3D9Device : public CHWDevice
68
+{
69
+public:
70
+    CD3D9Device();
71
+    virtual ~CD3D9Device();
72
+
73
+    virtual mfxStatus Init(
74
+        mfxHDL hWindow,
75
+        mfxU16 nViews,
76
+        mfxU32 nAdapterNum);
77
+    virtual mfxStatus Reset();
78
+    virtual mfxStatus GetHandle(mfxHandleType type, mfxHDL *pHdl);
79
+    virtual mfxStatus SetHandle(mfxHandleType type, mfxHDL hdl);
80
+    virtual mfxStatus RenderFrame(mfxFrameSurface1 * pSurface, mfxFrameAllocator * pmfxAlloc);
81
+    virtual void      UpdateTitle(double /*fps*/) { }
82
+    virtual void      Close() ;
83
+            void      DefineFormat(bool isA2rgb10) { m_bIsA2rgb10 = (isA2rgb10) ? TRUE : FALSE; }
84
+protected:
85
+    mfxStatus CreateVideoProcessors();
86
+    bool CheckOverlaySupport();
87
+    virtual mfxStatus FillD3DPP(mfxHDL hWindow, mfxU16 nViews, D3DPRESENT_PARAMETERS &D3DPP);
88
+private:
89
+    IDirect3D9Ex*               m_pD3D9;
90
+    IDirect3DDevice9Ex*         m_pD3DD9;
91
+    IDirect3DDeviceManager9*    m_pDeviceManager9;
92
+    D3DPRESENT_PARAMETERS       m_D3DPP;
93
+    UINT                        m_resetToken;
94
+
95
+    mfxU16                      m_nViews;
96
+    IGFXS3DControl*             m_pS3DControl;
97
+
98
+
99
+    D3DSURFACE_DESC                 m_backBufferDesc;
100
+
101
+    // service required to create video processors
102
+    IDirectXVideoProcessorService*  m_pDXVAVPS;
103
+    //left channel processor
104
+    IDirectXVideoProcessor*         m_pDXVAVP_Left;
105
+    // right channel processor
106
+    IDirectXVideoProcessor*         m_pDXVAVP_Right;
107
+
108
+    // target rectangle
109
+    RECT                            m_targetRect;
110
+
111
+    // various structures for DXVA2 calls
112
+    DXVA2_VideoDesc                 m_VideoDesc;
113
+    DXVA2_VideoProcessBltParams     m_BltParams;
114
+    DXVA2_VideoSample               m_Sample;
115
+
116
+    BOOL                            m_bIsA2rgb10;
117
+};
118
+
119
+#endif // #if defined( _WIN32 ) || defined ( _WIN64 )
120
\ No newline at end of file
121
obs-studio-0.16.6.tar.xz/plugins/obs-text/data/locale/nl-NL.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-text/data/locale/nl-NL.ini Changed
12
 
1
@@ -9,6 +9,10 @@
2
 Opacity="Dekking"
3
 Gradient="Kleurovergang"
4
 Gradient.Color="Overgangskleur"
5
+Gradient.Opacity="Kleurovergang Dekking"
6
+Gradient.Direction="Kleurovergang Richting"
7
+BkColor="Achtergrondkleur"
8
+BkOpacity="Achtergronddekking"
9
 Alignment="Uitlijning"
10
 Alignment.Left="Links"
11
 Alignment.Center="Midden"
12
obs-studio-0.17.0.tar.xz/plugins/obs-text/data/locale/tr-TR.ini Added
33
 
1
@@ -0,0 +1,31 @@
2
+TextGDIPlus="Metin (GDI+)"
3
+Font="Yazı Tipi"
4
+Text="Metin"
5
+ReadFromFile="Dosyadan oku"
6
+TextFile="Metin Dosyası (UTF-8)"
7
+Filter.TextFiles="Metin Dosyaları"
8
+Filter.AllFiles="Tüm Dosyalar"
9
+Color="Renk"
10
+Opacity="Opaklık"
11
+Gradient="Eğim"
12
+Gradient.Color="Eğim Rengi"
13
+Gradient.Opacity="Eğim Saydamlığı"
14
+Gradient.Direction="Eğim Yönü"
15
+BkColor="Arka Plan Rengi"
16
+BkOpacity="Arkaplan Saydamlığı"
17
+Alignment="Hizalama"
18
+Alignment.Left="Sol"
19
+Alignment.Center="Ortala"
20
+Alignment.Right="Sağ"
21
+Vertical="Dikey"
22
+VerticalAlignment="Dikey Hizalama"
23
+VerticalAlignment.Top="Üst"
24
+VerticalAlignment.Bottom="Alt"
25
+Outline="Anahat"
26
+Outline.Size="Anahat Boyutu"
27
+Outline.Color="Anahat Rengi"
28
+Outline.Opacity="Anahat Saydamlığı"
29
+UseCustomExtents="İsteğe Bağlı Metin Boyutu Kullan"
30
+Width="Genişlik"
31
+Height="Yükseklik"
32
+
33
obs-studio-0.16.6.tar.xz/plugins/obs-text/gdiplus/obs-text.cpp -> obs-studio-0.17.0.tar.xz/plugins/obs-text/gdiplus/obs-text.cpp Changed
9
 
1
@@ -787,7 +787,6 @@
2
    if (!tex)
3
        return;
4
 
5
-   gs_reset_blend_state();
6
    gs_effect_set_texture(gs_effect_get_param_by_name(effect, "image"), tex);
7
    gs_draw_sprite(tex, 0, cx, cy);
8
 }
9
obs-studio-0.16.6.tar.xz/plugins/obs-transitions/data/locale/tr-TR.ini -> obs-studio-0.17.0.tar.xz/plugins/obs-transitions/data/locale/tr-TR.ini Changed
51
 
1
@@ -2,10 +2,49 @@
2
 CutTransition="Kes"
3
 SwipeTransition="Kaydır"
4
 SlideTransition="Kaydır"
5
+FadeToColorTransition="Fade to Color"
6
 Direction="Yönlendir"
7
 Direction.Left="Sol"
8
 Direction.Right="Sağ"
9
 Direction.Up="Yukarı"
10
 Direction.Down="Aşağı"
11
+SwipeIn="İçeri Kaydır"
12
 Color="Renk"
13
+LumaWipe.Image="Görüntü"
14
+LumaWipe.Invert="Ters Çevir"
15
+LumaWipe.Softness="Yumuşaklık"
16
+LumaWipe.Type.BarndoorBottomLeft="Barndoor Bottom Left"
17
+LumaWipe.Type.BarndoorHorizontal="Barndoor Horizontal"
18
+LumaWipe.Type.BarndoorTopLeft="Barndoor Top Left"
19
+LumaWipe.Type.BarndoorVertical="Barndoor Vertical"
20
+LumaWipe.Type.BlindsHorizontal="Blinds Horizontal"
21
+LumaWipe.Type.BoxBottomLeft="Box Bottom Left"
22
+LumaWipe.Type.BoxBottomRight="Box Bottom Right"
23
+LumaWipe.Type.BoxTopLeft="Box Top Left"
24
+LumaWipe.Type.BoxTopRight="Box Top Right"
25
+LumaWipe.Type.Burst="Burst"
26
+LumaWipe.Type.CheckerboardSmall="Checkerboard Small"
27
+LumaWipe.Type.Circles="Circles"
28
+LumaWipe.Type.Clock="Clock"
29
+LumaWipe.Type.Cloud="Cloud"
30
+LumaWipe.Type.Curtain="Curtain"
31
+LumaWipe.Type.Fan="Fan"
32
+LumaWipe.Type.Fractal="Fractal"
33
+LumaWipe.Type.Iris="Iris"
34
+LumaWipe.Type.LinearHorizontal="Linear Horizontal"
35
+LumaWipe.Type.LinearTopLeft="Linear Top Left"
36
+LumaWipe.Type.LinearTopRight="Linear Top Right"
37
+LumaWipe.Type.LinearVertical="Linear Vertical"
38
+LumaWipe.Type.ParallelZigzagHorizontal="Parallel Zigzag Horizontal"
39
+LumaWipe.Type.ParallelZigzagVertical="Parallel Zigzag Vertical"
40
+LumaWipe.Type.Sinus9="Sinus 9"
41
+LumaWipe.Type.Spiral="Spiral"
42
+LumaWipe.Type.Square="Square"
43
+LumaWipe.Type.Squares="Squares"
44
+LumaWipe.Type.Stripes="Stripes"
45
+LumaWipe.Type.StripsHorizontal="Strips Horizontal"
46
+LumaWipe.Type.StripsVertical="Strips Vertical"
47
+LumaWipe.Type.Watercolor="Watercolor"
48
+LumaWipe.Type.ZigzagHorizontal="Zigzag Horizontal"
49
+LumaWipe.Type.ZigzagVertical="Zigzag Vertical"
50
 
51
obs-studio-0.16.6.tar.xz/plugins/obs-transitions/data/slide_transition.effect -> obs-studio-0.17.0.tar.xz/plugins/obs-transitions/data/slide_transition.effect Changed
19
 
1
@@ -28,12 +28,11 @@
2
 {
3
    float2 tex_a_uv = v_in.uv + tex_a_dir;
4
    float2 tex_b_uv = v_in.uv - tex_b_dir;
5
-   
6
-   float4 tex_a_sample = tex_a.Sample(textureSampler, tex_a_uv);
7
-   float4 tex_b_sample = tex_b.Sample(textureSampler, tex_b_uv);
8
-   
9
-   float val = saturate(abs((tex_a_uv.x - saturate(tex_a_uv.x)) + (tex_a_uv.y - saturate(tex_a_uv.y))) * 65535);
10
-   return lerp(tex_a_sample, tex_b_sample, val);
11
+
12
+   return (tex_a_uv.x - saturate(tex_a_uv.x) != 0.0) ||
13
+          (tex_a_uv.y - saturate(tex_a_uv.y) != 0.0)
14
+          ? tex_b.Sample(textureSampler, tex_b_uv)
15
+          : tex_a.Sample(textureSampler, tex_a_uv);
16
 }
17
 
18
 technique Slide
19
obs-studio-0.16.6.tar.xz/plugins/rtmp-services/data/package.json -> obs-studio-0.17.0.tar.xz/plugins/rtmp-services/data/package.json Changed
14
 
1
@@ -1,10 +1,10 @@
2
 {
3
    "url": "https://obsproject.com/obs2_update/rtmp-services",
4
-   "version": 41,
5
+   "version": 43,
6
    "files": [
7
        {
8
            "name": "services.json",
9
-           "version": 41
10
+           "version": 43
11
        }
12
    ]
13
 }
14
obs-studio-0.16.6.tar.xz/plugins/rtmp-services/data/services.json -> obs-studio-0.17.0.tar.xz/plugins/rtmp-services/data/services.json Changed
119
 
1
@@ -346,15 +346,6 @@
2
             ]
3
         },
4
         {
5
-            "name": "mSportz",
6
-            "servers": [
7
-                {
8
-                    "name": "Primary",
9
-                    "url": "rtmp://52.21.78.175/mSports"
10
-                }
11
-            ]
12
-        },
13
-        {
14
             "name": "Switchboard Live (Joicaster)",
15
             "servers": [
16
                 {
17
@@ -439,15 +430,6 @@
18
             ]
19
         },
20
         {
21
-            "name": "Streamup",
22
-            "servers": [
23
-                {
24
-                    "name": "Worldwide",
25
-                    "url": "rtmp://origin.streamuplive.com/app"
26
-                }
27
-            ]
28
-        },
29
-        {
30
             "name": "connectcast.tv",
31
             "servers": [
32
                 {
33
@@ -557,60 +539,56 @@
34
             "common": true,
35
             "servers": [
36
                 {
37
-                    "name": "US-West (San Jose, California)",
38
-                    "url": "rtmp://us-west.restream.io/live"
39
-                },
40
-                {
41
-                    "name": "US-West (Los Angeles, California)",
42
-                    "url": "rtmp://us-la.restream.io/live"
43
-                },
44
-                {
45
-                    "name": "US-West (Seattle, Washington)",
46
-                    "url": "rtmp://us-seattle.restream.io/live"
47
+                    "name": "EU-West (London, GB)",
48
+                    "url": "rtmp://eu-london.restream.io/live"
49
                 },
50
                 {
51
-                    "name": "US-Central (Dallas, Texas)",
52
-                    "url": "rtmp://us-central.restream.io/live"
53
+                    "name": "EU-West (Amsterdam, NL)",
54
+                    "url": "rtmp://eu-ams.restream.io/live"
55
                 },
56
                 {
57
-                    "name": "US-East (Washington, D.C.)",
58
-                    "url": "rtmp://us-east.restream.io/live"
59
+                    "name": "EU-Central (Frankfurt, DE)",
60
+                    "url": "rtmp://eu-central.restream.io/live"
61
                 },
62
                 {
63
-                    "name": "NA-East (Toronto, Canada)",
64
-                    "url": "rtmp://na-toronto.restream.io/live"
65
+                    "name": "EU-East (Falkenstein, DE)",
66
+                    "url": "rtmp://eu-east.restream.io/live"
67
                 },
68
                 {
69
-                    "name": "EU-Central (Frankfurt, Germany)",
70
-                    "url": "rtmp://eu-central.restream.io/live"
71
+                    "name": "Russia (Moscow)",
72
+                    "url": "rtmp://ru.restream.io/live"
73
                 },
74
                 {
75
-                    "name": "EU-Central 2 (Frankfurt, Germany)",
76
-                    "url": "rtmp://eu.restream.io/live"
77
+                    "name": "US-West (Seattle, WA)",
78
+                    "url": "rtmp://us-seattle.restream.io/live"
79
                 },
80
                 {
81
-                    "name": "EU-West (Amsterdam, Netherlands)",
82
-                    "url": "rtmp://eu-ams.restream.io/live"
83
+                    "name": "US-West (San Jose, CA)",
84
+                    "url": "rtmp://us-west.restream.io/live"
85
                 },
86
                 {
87
-                    "name": "EU-West (London, Great Britain)",
88
-                    "url": "rtmp://eu-london.restream.io/live"
89
+                    "name": "US-Central (Dallas, TX)",
90
+                    "url": "rtmp://us-central.restream.io/live"
91
                 },
92
                 {
93
-                    "name": "Australia (Sydney)",
94
-                    "url": "rtmp://au.restream.io/live"
95
+                    "name": "US-East (Washington, DC)",
96
+                    "url": "rtmp://us-east.restream.io/live"
97
                 },
98
                 {
99
-                    "name": "Australia Secondary (Sydney)",
100
-                    "url": "rtmp://au-secondary.restream.io/live"
101
+                    "name": "NA-East (Toronto, Canada)",
102
+                    "url": "rtmp://na-toronto.restream.io/live"
103
                 },
104
                 {
105
-                    "name": "South America (Sao Paulo, Brazil)",
106
+                    "name": "SA (Saint Paul, Brazil)",
107
                     "url": "rtmp://sa.restream.io/live"
108
                 },
109
                 {
110
                     "name": "Asia (Singapore)",
111
                     "url": "rtmp://singapore.restream.io/live"
112
+                },
113
+                {
114
+                    "name": "Australia (Sydney)",
115
+                    "url": "rtmp://au.restream.io/live"
116
                 }
117
             ],
118
             "recommended": {
119
obs-studio-0.17.0.tar.xz/plugins/vlc-video/data/locale/tr-TR.ini Added
5
 
1
@@ -0,0 +1,3 @@
2
+VLCSource="VLC Video Kaynağı"
3
+Playlist="Oynatma Listesi"
4
+
5
obs-studio-0.16.6.tar.xz/plugins/win-capture/CMakeLists.txt -> obs-studio-0.17.0.tar.xz/plugins/win-capture/CMakeLists.txt Changed
19
 
1
@@ -1,7 +1,9 @@
2
 project(win-capture)
3
 
4
 set(win-capture_HEADERS
5
+   nt-stuff.h
6
    obfuscate.h
7
+   app-helpers.h
8
    hook-helpers.h
9
    inject-library.h
10
    cursor-capture.h
11
@@ -12,6 +14,7 @@
12
 set(win-capture_SOURCES
13
    dc-capture.c
14
    obfuscate.c
15
+   app-helpers.c
16
    inject-library.c
17
    cursor-capture.c
18
    game-capture.c
19
obs-studio-0.17.0.tar.xz/plugins/win-capture/app-helpers.c Added
79
 
1
@@ -0,0 +1,77 @@
2
+#include <windows.h>
3
+#include <stdio.h>
4
+#include "app-helpers.h"
5
+#include "nt-stuff.h"
6
+
7
+WINADVAPI WINAPI ConvertSidToStringSidW(PSID sid, LPWSTR *str);
8
+
9
+bool is_app(HANDLE process)
10
+{
11
+   DWORD size_ret;
12
+   DWORD ret = 0;
13
+   HANDLE token;
14
+
15
+   if (OpenProcessToken(process, TOKEN_QUERY, &token)) {
16
+       BOOL success = GetTokenInformation(token, TokenIsAppContainer,
17
+               &ret, sizeof(ret), &size_ret);
18
+       if (!success) {
19
+           DWORD error = GetLastError();
20
+           int test = 0;
21
+       }
22
+
23
+       CloseHandle(token);
24
+   }
25
+   return !!ret;
26
+}
27
+
28
+wchar_t *get_app_sid(HANDLE process)
29
+{
30
+   wchar_t *ret = NULL;
31
+   DWORD size_ret;
32
+   BOOL success;
33
+   HANDLE token;
34
+
35
+   if (OpenProcessToken(process, TOKEN_QUERY, &token)) {
36
+       DWORD info_len = GetSidLengthRequired(12) +
37
+           sizeof(TOKEN_APPCONTAINER_INFORMATION);
38
+
39
+       PTOKEN_APPCONTAINER_INFORMATION info = malloc(info_len);
40
+
41
+       success = GetTokenInformation(token, TokenAppContainerSid,
42
+               info, info_len, &size_ret);
43
+       if (success)
44
+           ConvertSidToStringSidW(info->TokenAppContainer, &ret);
45
+
46
+       free(info);
47
+       CloseHandle(token);
48
+   }
49
+
50
+   return ret;
51
+}
52
+
53
+static const wchar_t *path_format =
54
+   L"\\Sessions\\%lu\\AppContainerNamedObjects\\%s\\%s";
55
+
56
+HANDLE open_app_mutex(const wchar_t *sid, const wchar_t *name)
57
+{
58
+   wchar_t path[MAX_PATH];
59
+   DWORD session_id = WTSGetActiveConsoleSessionId();
60
+   _snwprintf(path, MAX_PATH, path_format, session_id, sid, name);
61
+   return nt_open_mutex(path);
62
+}
63
+
64
+HANDLE open_app_event(const wchar_t *sid, const wchar_t *name)
65
+{
66
+   wchar_t path[MAX_PATH];
67
+   DWORD session_id = WTSGetActiveConsoleSessionId();
68
+   _snwprintf(path, MAX_PATH, path_format, session_id, sid, name);
69
+   return nt_open_event(path);
70
+}
71
+
72
+HANDLE open_app_map(const wchar_t *sid, const wchar_t *name)
73
+{
74
+   wchar_t path[MAX_PATH];
75
+   DWORD session_id = WTSGetActiveConsoleSessionId();
76
+   _snwprintf(path, MAX_PATH, path_format, session_id, sid, name);
77
+   return nt_open_map(path);
78
+}
79
obs-studio-0.17.0.tar.xz/plugins/win-capture/app-helpers.h Added
11
 
1
@@ -0,0 +1,9 @@
2
+#pragma once
3
+
4
+#include <stdbool.h>
5
+
6
+extern bool is_app(HANDLE process);
7
+extern wchar_t *get_app_sid(HANDLE process);
8
+extern HANDLE open_app_mutex(const wchar_t *sid, const wchar_t *name);
9
+extern HANDLE open_app_event(const wchar_t *sid, const wchar_t *name);
10
+extern HANDLE open_app_map(const wchar_t *sid, const wchar_t *name);
11
obs-studio-0.16.6.tar.xz/plugins/win-capture/data/locale/nl-NL.ini -> obs-studio-0.17.0.tar.xz/plugins/win-capture/data/locale/nl-NL.ini Changed
10
 
1
@@ -13,7 +13,7 @@
2
 GameCapture="Gamecapture"
3
 GameCapture.AnyFullscreen="Capture elke full-screen applicatie"
4
 GameCapture.CaptureWindow="Specifiek venster opnemen"
5
-GameCapture.UseHotkey="Venster op voorgrond opnemen met hotkey"
6
+GameCapture.UseHotkey="Venster op voorgrond opnemen met sneltoets"
7
 GameCapture.ForceScaling="Forceer Schalen"
8
 GameCapture.ScaleRes="Geschaalde resolutie"
9
 GameCapture.LimitFramerate="Begrens frame rate van de opname"
10
obs-studio-0.16.6.tar.xz/plugins/win-capture/data/locale/tr-TR.ini -> obs-studio-0.17.0.tar.xz/plugins/win-capture/data/locale/tr-TR.ini Changed
7
 
1
@@ -17,4 +17,5 @@
2
 GameCapture.LimitFramerate="Yakalama kare hızını sınırlandır"
3
 GameCapture.CaptureOverlays="Üçüncü taraf katmanları yakala (steam vb.)"
4
 GameCapture.AntiCheatHook="Anti-hile uyumluluğunu kullan"
5
+Mode="Mod"
6
 
7
obs-studio-0.16.6.tar.xz/plugins/win-capture/game-capture.c -> obs-studio-0.17.0.tar.xz/plugins/win-capture/game-capture.c Changed
592
 
1
@@ -12,6 +12,8 @@
2
 #include "graphics-hook-info.h"
3
 #include "window-helpers.h"
4
 #include "cursor-capture.h"
5
+#include "app-helpers.h"
6
+#include "nt-stuff.h"
7
 
8
 #define do_log(level, format, ...) \
9
    blog(level, "[game-capture: '%s'] " format, \
10
@@ -127,13 +129,16 @@
11
    bool                          dwm_capture : 1;
12
    bool                          initial_config : 1;
13
    bool                          convert_16bit : 1;
14
+   bool                          is_app : 1;
15
 
16
    struct game_capture_config    config;
17
 
18
    ipc_pipe_server_t             pipe;
19
    gs_texture_t                  *texture;
20
    struct hook_info              *global_hook_info;
21
-   HANDLE                        keep_alive;
22
+   HANDLE                        keepalive_thread;
23
+   DWORD                         keepalive_thread_id;
24
+   HANDLE                        hook_init;
25
    HANDLE                        hook_restart;
26
    HANDLE                        hook_stop;
27
    HANDLE                        hook_ready;
28
@@ -142,6 +147,8 @@
29
    HANDLE                        global_hook_info_map;
30
    HANDLE                        target_process;
31
    HANDLE                        texture_mutexes[2];
32
+   wchar_t                       *app_sid;
33
+   int                           retrying;
34
 
35
    union {
36
        struct {
37
@@ -159,6 +166,61 @@
38
 struct graphics_offsets offsets32 = {0};
39
 struct graphics_offsets offsets64 = {0};
40
 
41
+static inline bool use_anticheat(struct game_capture *gc)
42
+{
43
+   return gc->config.anticheat_hook && !gc->is_app;
44
+}
45
+
46
+static inline HANDLE open_mutex_plus_id(struct game_capture *gc,
47
+       const wchar_t *name, DWORD id)
48
+{
49
+   wchar_t new_name[64];
50
+   _snwprintf(new_name, 64, L"%s%lu", name, id);
51
+   return gc->is_app
52
+       ? open_app_mutex(gc->app_sid, new_name)
53
+       : open_mutex(new_name);
54
+}
55
+
56
+static inline HANDLE open_mutex_gc(struct game_capture *gc,
57
+       const wchar_t *name)
58
+{
59
+   return open_mutex_plus_id(gc, name, gc->process_id);
60
+}
61
+
62
+static inline HANDLE open_event_plus_id(struct game_capture *gc,
63
+       const wchar_t *name, DWORD id)
64
+{
65
+   wchar_t new_name[64];
66
+   _snwprintf(new_name, 64, L"%s%lu", name, id);
67
+   return gc->is_app
68
+       ? open_app_event(gc->app_sid, new_name)
69
+       : open_event(new_name);
70
+}
71
+
72
+static inline HANDLE open_event_gc(struct game_capture *gc,
73
+       const wchar_t *name)
74
+{
75
+   return open_event_plus_id(gc, name, gc->process_id);
76
+}
77
+
78
+static inline HANDLE open_map_plus_id(struct game_capture *gc,
79
+       const wchar_t *name, DWORD id)
80
+{
81
+   wchar_t new_name[64];
82
+   _snwprintf(new_name, 64, L"%s%lu", name, id);
83
+
84
+   debug("map id: %S", new_name);
85
+
86
+   return gc->is_app
87
+       ? open_app_map(gc->app_sid, new_name)
88
+       : OpenFileMappingW(GC_MAPPING_FLAGS, false, new_name);
89
+}
90
+
91
+static inline HANDLE open_hook_info(struct game_capture *gc)
92
+{
93
+   return open_map_plus_id(gc, SHMEM_HOOK_INFO, gc->process_id);
94
+}
95
+
96
 static inline enum gs_color_format convert_format(uint32_t format)
97
 {
98
    switch (format) {
99
@@ -219,11 +281,22 @@
100
        gc->data = NULL;
101
    }
102
 
103
-   close_handle(&gc->keep_alive);
104
+   if (gc->keepalive_thread) {
105
+       PostThreadMessage(gc->keepalive_thread_id, WM_QUIT, 0, 0);
106
+       WaitForSingleObject(gc->keepalive_thread, 300);
107
+       close_handle(&gc->keepalive_thread);
108
+   }
109
+
110
+   if (gc->app_sid) {
111
+       LocalFree(gc->app_sid);
112
+       gc->app_sid = NULL;
113
+   }
114
+
115
    close_handle(&gc->hook_restart);
116
    close_handle(&gc->hook_stop);
117
    close_handle(&gc->hook_ready);
118
    close_handle(&gc->hook_exit);
119
+   close_handle(&gc->hook_init);
120
    close_handle(&gc->hook_data_map);
121
    close_handle(&gc->global_hook_info_map);
122
    close_handle(&gc->target_process);
123
@@ -237,10 +310,16 @@
124
        gc->texture = NULL;
125
    }
126
 
127
+   if (gc->active)
128
+       info("capture stopped");
129
+
130
    gc->copy_texture = NULL;
131
    gc->wait_for_target_startup = false;
132
    gc->active = false;
133
    gc->capturing = false;
134
+
135
+   if (gc->retrying)
136
+       gc->retrying--;
137
 }
138
 
139
 static inline void free_config(struct game_capture_config *config)
140
@@ -473,21 +552,6 @@
141
    return gc;
142
 }
143
 
144
-static inline HANDLE create_event_id(bool manual_reset, bool initial_state,
145
-       const char *name, DWORD process_id)
146
-{
147
-   char new_name[128];
148
-   sprintf(new_name, "%s%lu", name, process_id);
149
-   return CreateEventA(NULL, manual_reset, initial_state, new_name);
150
-}
151
-
152
-static inline HANDLE open_event_id(const char *name, DWORD process_id)
153
-{
154
-   char new_name[128];
155
-   sprintf(new_name, "%s%lu", name, process_id);
156
-   return OpenEventA(EVENT_ALL_ACCESS, false, new_name);
157
-}
158
-
159
 #define STOP_BEING_BAD \
160
    "  This is most likely due to security software. Please make sure " \
161
         "that the OBS installation folder is excluded/ignored in the "      \
162
@@ -570,30 +634,104 @@
163
    }
164
 
165
    gc->process_is_64bit = is_64bit_process(gc->target_process);
166
+   gc->is_app = is_app(gc->target_process);
167
+   if (gc->is_app) {
168
+       gc->app_sid = get_app_sid(gc->target_process);
169
+   }
170
    return true;
171
 }
172
 
173
+struct keepalive_data {
174
+   struct game_capture *gc;
175
+   HANDLE initialized;
176
+};
177
+
178
+#define DEF_FLAGS (WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS)
179
+
180
+static DWORD WINAPI keepalive_window_thread(struct keepalive_data *data)
181
+{
182
+   HANDLE initialized = data->initialized;
183
+   struct game_capture *gc = data->gc;
184
+   wchar_t new_name[64];
185
+   WNDCLASSW wc;
186
+   HWND window;
187
+   MSG msg;
188
+
189
+   _snwprintf(new_name, sizeof(new_name), L"%s%lu",
190
+           WINDOW_HOOK_KEEPALIVE, gc->process_id);
191
+
192
+   memset(&wc, 0, sizeof(wc));
193
+   wc.style = CS_OWNDC;
194
+   wc.hInstance = GetModuleHandleW(NULL);
195
+   wc.lpfnWndProc = (WNDPROC)DefWindowProc;
196
+   wc.lpszClassName = new_name;
197
+
198
+   if (!RegisterClass(&wc)) {
199
+       warn("Failed to create keepalive window class: %lu",
200
+               GetLastError());
201
+       return 0;
202
+   }
203
+
204
+   window = CreateWindowExW(0, new_name, NULL, DEF_FLAGS, 0, 0, 1, 1,
205
+           NULL, NULL, wc.hInstance, NULL);
206
+   if (!window) {
207
+       warn("Failed to create keepalive window: %lu",
208
+               GetLastError());
209
+       return 0;
210
+   }
211
+
212
+   SetEvent(initialized);
213
+
214
+   while (GetMessage(&msg, NULL, 0, 0)) {
215
+       TranslateMessage(&msg);
216
+       DispatchMessage(&msg);
217
+   }
218
+
219
+   DestroyWindow(window);
220
+   UnregisterClassW(new_name, wc.hInstance);
221
+
222
+   return 0;
223
+}
224
+
225
 static inline bool init_keepalive(struct game_capture *gc)
226
 {
227
-   gc->keep_alive = create_event_id(false, false, EVENT_HOOK_KEEPALIVE,
228
-           gc->process_id);
229
-   if (!gc->keep_alive) {
230
-       warn("failed to create keepalive event");
231
+   struct keepalive_data data;
232
+   HANDLE initialized = CreateEvent(NULL, false, false, NULL);
233
+
234
+   data.gc = gc;
235
+   data.initialized = initialized;
236
+
237
+   gc->keepalive_thread = CreateThread(NULL, 0,
238
+           (LPTHREAD_START_ROUTINE)keepalive_window_thread,
239
+           &data, 0, &gc->keepalive_thread_id);
240
+   if (!gc->keepalive_thread) {
241
+       warn("Failed to create keepalive window thread: %lu",
242
+               GetLastError());
243
        return false;
244
    }
245
 
246
+   WaitForSingleObject(initialized, INFINITE);
247
+   CloseHandle(initialized);
248
+
249
    return true;
250
 }
251
 
252
 static inline bool init_texture_mutexes(struct game_capture *gc)
253
 {
254
-   gc->texture_mutexes[0] = get_mutex_plus_id(MUTEX_TEXTURE1,
255
-           gc->process_id);
256
-   gc->texture_mutexes[1] = get_mutex_plus_id(MUTEX_TEXTURE2,
257
-           gc->process_id);
258
+   gc->texture_mutexes[0] = open_mutex_gc(gc, MUTEX_TEXTURE1);
259
+   gc->texture_mutexes[1] = open_mutex_gc(gc, MUTEX_TEXTURE2);
260
 
261
    if (!gc->texture_mutexes[0] || !gc->texture_mutexes[1]) {
262
-       warn("failed to create texture mutexes: %lu", GetLastError());
263
+       DWORD error = GetLastError();
264
+       if (error == 2) {
265
+           if (!gc->retrying) {
266
+               gc->retrying = 2;
267
+               info("hook not loaded yet, retrying..");
268
+           }
269
+       } else {
270
+           warn("failed to open texture mutexes: %lu",
271
+                   GetLastError());
272
+       }
273
        return false;
274
    }
275
 
276
@@ -603,7 +741,7 @@
277
 /* if there's already a hook in the process, then signal and start */
278
 static inline bool attempt_existing_hook(struct game_capture *gc)
279
 {
280
-   gc->hook_restart = open_event_id(EVENT_CAPTURE_RESTART, gc->process_id);
281
+   gc->hook_restart = open_event_gc(gc, EVENT_CAPTURE_RESTART);
282
    if (gc->hook_restart) {
283
        debug("existing hook found, signaling process: %s",
284
                gc->config.executable);
285
@@ -635,7 +773,7 @@
286
 
287
 static inline bool init_hook_info(struct game_capture *gc)
288
 {
289
-   gc->global_hook_info_map = get_hook_info(gc->process_id);
290
+   gc->global_hook_info_map = open_hook_info(gc);
291
    if (!gc->global_hook_info_map) {
292
        warn("init_hook_info: get_hook_info failed: %lu",
293
                GetLastError());
294
@@ -750,7 +888,7 @@
295
    wchar_t *command_line_w = malloc(4096 * sizeof(wchar_t));
296
    wchar_t *inject_path_w;
297
    wchar_t *hook_dll_w;
298
-   bool anti_cheat = gc->config.anticheat_hook;
299
+   bool anti_cheat = use_anticheat(gc);
300
    PROCESS_INFORMATION pi = {0};
301
    STARTUPINFO si = {0};
302
    bool success = false;
303
@@ -812,11 +950,11 @@
304
    matching_architecture = !gc->process_is_64bit;
305
 #endif
306
 
307
-   if (matching_architecture && !gc->config.anticheat_hook) {
308
+   if (matching_architecture && !use_anticheat(gc)) {
309
        info("using direct hook");
310
        success = hook_direct(gc, hook_path);
311
    } else {
312
-       info("using helper (%s hook)", gc->config.anticheat_hook ?
313
+       info("using helper (%s hook)", use_anticheat(gc) ?
314
                "compatibility" : "direct");
315
        success = create_inject_process(gc, inject_path, hook_dll);
316
    }
317
@@ -838,7 +976,11 @@
318
    "devenv",
319
    "taskmgr",
320
    "systemsettings",
321
+   "applicationframehost",
322
    "cmd",
323
+   "shellexperiencehost",
324
+   "winstore.app",
325
+   "searchui",
326
    NULL
327
 };
328
 
329
@@ -860,6 +1002,13 @@
330
    return false;
331
 }
332
 
333
+static bool target_suspended(struct game_capture *gc)
334
+{
335
+   return thread_is_suspended(gc->process_id, gc->thread_id);
336
+}
337
+
338
+static bool init_events(struct game_capture *gc);
339
+
340
 static bool init_hook(struct game_capture *gc)
341
 {
342
    struct dstr exe = {0};
343
@@ -871,8 +1020,9 @@
344
                    exe.array);
345
        }
346
    } else {
347
-       info("attempting to hook process: %s", gc->executable.array);
348
-       dstr_copy_dstr(&exe, &gc->executable);
349
+       if (get_window_exe(&exe, gc->next_window)) {
350
+           info("attempting to hook process: %s", exe.array);
351
+       }
352
    }
353
 
354
    blacklisted_process = is_blacklisted_exe(exe.array);
355
@@ -883,16 +1033,13 @@
356
    if (blacklisted_process) {
357
        return false;
358
    }
359
-   if (!open_target_process(gc)) {
360
+   if (target_suspended(gc)) {
361
        return false;
362
    }
363
-   if (!init_keepalive(gc)) {
364
-       return false;
365
-   }
366
-   if (!init_texture_mutexes(gc)) {
367
+   if (!open_target_process(gc)) {
368
        return false;
369
    }
370
-   if (!init_hook_info(gc)) {
371
+   if (!init_keepalive(gc)) {
372
        return false;
373
    }
374
    if (!init_pipe(gc)) {
375
@@ -903,22 +1050,45 @@
376
            return false;
377
        }
378
    }
379
+   if (!init_texture_mutexes(gc)) {
380
+       return false;
381
+   }
382
+   if (!init_hook_info(gc)) {
383
+       return false;
384
+   }
385
+   if (!init_events(gc)) {
386
+       return false;
387
+   }
388
+
389
+   SetEvent(gc->hook_init);
390
 
391
    gc->window = gc->next_window;
392
    gc->next_window = NULL;
393
    gc->active = true;
394
+   gc->retrying = 0;
395
    return true;
396
 }
397
 
398
 static void setup_window(struct game_capture *gc, HWND window)
399
 {
400
-   DWORD process_id = 0;
401
    HANDLE hook_restart;
402
+   HANDLE process;
403
 
404
-   GetWindowThreadProcessId(window, &process_id);
405
+   GetWindowThreadProcessId(window, &gc->process_id);
406
+   if (gc->process_id) {
407
+       process = open_process(PROCESS_QUERY_INFORMATION,
408
+           false, gc->process_id);
409
+       if (process) {
410
+           gc->is_app = is_app(process);
411
+           if (gc->is_app) {
412
+               gc->app_sid = get_app_sid(process);
413
+           }
414
+           CloseHandle(process);
415
+       }
416
+   }
417
 
418
    /* do not wait if we're re-hooking a process */
419
-   hook_restart = open_event_id(EVENT_CAPTURE_RESTART, process_id);
420
+   hook_restart = open_event_gc(gc, EVENT_CAPTURE_RESTART);
421
    if (hook_restart) {
422
        gc->wait_for_target_startup = false;
423
        CloseHandle(hook_restart);
424
@@ -1019,7 +1189,9 @@
425
        if (gc->process_id == GetCurrentProcessId())
426
            return;
427
 
428
-       if (!gc->thread_id || !gc->process_id) {
429
+       if (!gc->thread_id && gc->process_id)
430
+           return;
431
+       if (!gc->process_id) {
432
            warn("error acquiring, failed to get window "
433
                    "thread/process ids: %lu",
434
                    GetLastError());
435
@@ -1038,8 +1210,7 @@
436
 static inline bool init_events(struct game_capture *gc)
437
 {
438
    if (!gc->hook_restart) {
439
-       gc->hook_restart = get_event_plus_id(EVENT_CAPTURE_RESTART,
440
-               gc->process_id);
441
+       gc->hook_restart = open_event_gc(gc, EVENT_CAPTURE_RESTART);
442
        if (!gc->hook_restart) {
443
            warn("init_events: failed to get hook_restart "
444
                 "event: %lu", GetLastError());
445
@@ -1048,8 +1219,7 @@
446
    }
447
 
448
    if (!gc->hook_stop) {
449
-       gc->hook_stop = get_event_plus_id(EVENT_CAPTURE_STOP,
450
-               gc->process_id);
451
+       gc->hook_stop = open_event_gc(gc, EVENT_CAPTURE_STOP);
452
        if (!gc->hook_stop) {
453
            warn("init_events: failed to get hook_stop event: %lu",
454
                    GetLastError());
455
@@ -1057,9 +1227,17 @@
456
        }
457
    }
458
 
459
+   if (!gc->hook_init) {
460
+       gc->hook_init = open_event_gc(gc, EVENT_HOOK_INIT);
461
+       if (!gc->hook_init) {
462
+           warn("init_events: failed to get hook_init event: %lu",
463
+                   GetLastError());
464
+           return false;
465
+       }
466
+   }
467
+
468
    if (!gc->hook_ready) {
469
-       gc->hook_ready = get_event_plus_id(EVENT_HOOK_READY,
470
-               gc->process_id);
471
+       gc->hook_ready = open_event_gc(gc, EVENT_HOOK_READY);
472
        if (!gc->hook_ready) {
473
            warn("init_events: failed to get hook_ready event: %lu",
474
                    GetLastError());
475
@@ -1068,8 +1246,7 @@
476
    }
477
 
478
    if (!gc->hook_exit) {
479
-       gc->hook_exit = get_event_plus_id(EVENT_HOOK_EXIT,
480
-               gc->process_id);
481
+       gc->hook_exit = open_event_gc(gc, EVENT_HOOK_EXIT);
482
        if (!gc->hook_exit) {
483
            warn("init_events: failed to get hook_exit event: %lu",
484
                    GetLastError());
485
@@ -1088,9 +1265,6 @@
486
 
487
 static inline enum capture_result init_capture_data(struct game_capture *gc)
488
 {
489
-   char name[64];
490
-   sprintf(name, "%s%u", SHMEM_TEXTURE, gc->global_hook_info->map_id);
491
-
492
    gc->cx = gc->global_hook_info->cx;
493
    gc->cy = gc->global_hook_info->cy;
494
    gc->pitch = gc->global_hook_info->pitch;
495
@@ -1102,7 +1276,8 @@
496
 
497
    CloseHandle(gc->hook_data_map);
498
 
499
-   gc->hook_data_map = OpenFileMappingA(FILE_MAP_ALL_ACCESS, false, name);
500
+   gc->hook_data_map = open_map_plus_id(gc, SHMEM_TEXTURE,
501
+           gc->global_hook_info->map_id);
502
    if (!gc->hook_data_map) {
503
        DWORD error = GetLastError();
504
        if (error == 2) {
505
@@ -1410,17 +1585,20 @@
506
 
507
 static bool start_capture(struct game_capture *gc)
508
 {
509
-   if (!init_events(gc)) {
510
-       return false;
511
-   }
512
+   debug("Starting capture");
513
+
514
    if (gc->global_hook_info->type == CAPTURE_TYPE_MEMORY) {
515
        if (!init_shmem_capture(gc)) {
516
            return false;
517
        }
518
+
519
+       info("memory capture successful");
520
    } else {
521
        if (!init_shtex_capture(gc)) {
522
            return false;
523
        }
524
+
525
+       info("shared texture capture successful");
526
    }
527
 
528
    return true;
529
@@ -1443,6 +1621,9 @@
530
    if (activate_now) {
531
        HWND hwnd = (HWND)os_atomic_load_long(&gc->hotkey_window);
532
 
533
+       if (is_uwp_window(hwnd))
534
+           hwnd = get_uwp_actual_window(hwnd);
535
+
536
        if (get_window_exe(&gc->executable, hwnd)) {
537
            get_window_title(&gc->title, hwnd);
538
            get_window_class(&gc->class, hwnd);
539
@@ -1471,6 +1652,7 @@
540
    }
541
 
542
    if (gc->hook_stop && object_signalled(gc->hook_stop)) {
543
+       debug("hook stop signal received");
544
        stop_capture(gc);
545
    }
546
    if (gc->active && deactivate) {
547
@@ -1478,8 +1660,7 @@
548
    }
549
 
550
    if (gc->active && !gc->hook_ready && gc->process_id) {
551
-       gc->hook_ready = get_event_plus_id(EVENT_HOOK_READY,
552
-               gc->process_id);
553
+       gc->hook_ready = open_event_gc(gc, EVENT_HOOK_READY);
554
    }
555
 
556
    if (gc->injector_process && object_signalled(gc->injector_process)) {
557
@@ -1499,10 +1680,13 @@
558
    }
559
 
560
    if (gc->hook_ready && object_signalled(gc->hook_ready)) {
561
+       debug("capture initializing!");
562
        enum capture_result result = init_capture_data(gc);
563
 
564
        if (result == CAPTURE_SUCCESS)
565
            gc->capturing = start_capture(gc);
566
+       else
567
+           debug("init_capture_data failed");
568
 
569
        if (result != CAPTURE_RETRY && !gc->capturing) {
570
            gc->retry_interval = ERROR_RETRY_INTERVAL;
571
@@ -1554,13 +1738,17 @@
572
 static inline void game_capture_render_cursor(struct game_capture *gc)
573
 {
574
    POINT p = {0};
575
+   HWND window;
576
 
577
-   if (!gc->global_hook_info->window ||
578
-       !gc->global_hook_info->base_cx ||
579
+   if (!gc->global_hook_info->base_cx ||
580
        !gc->global_hook_info->base_cy)
581
        return;
582
 
583
-   ClientToScreen((HWND)(uintptr_t)gc->global_hook_info->window, &p);
584
+   window = !!gc->global_hook_info->window
585
+       ? (HWND)(uintptr_t)gc->global_hook_info->window
586
+       : gc->window;
587
+
588
+   ClientToScreen(window, &p);
589
 
590
    float x_scale = (float)gc->global_hook_info->cx /
591
        (float)gc->global_hook_info->base_cx;
592
obs-studio-0.16.6.tar.xz/plugins/win-capture/get-graphics-offsets/CMakeLists.txt -> obs-studio-0.17.0.tar.xz/plugins/win-capture/get-graphics-offsets/CMakeLists.txt Changed
12
 
1
@@ -11,6 +11,10 @@
2
    d3d8-offsets.cpp
3
    d3d9-offsets.cpp)
4
 
5
+if(MSVC)
6
+   add_compile_options("$<$<CONFIG:RelWithDebInfo>:/MT>")
7
+endif()
8
+
9
 add_executable(get-graphics-offsets
10
    ${get-graphics-offsets_SOURCES}
11
    ${get-graphics-offsets_HEADERS})
12
obs-studio-0.16.6.tar.xz/plugins/win-capture/get-graphics-offsets/d3d8-offsets.cpp -> obs-studio-0.17.0.tar.xz/plugins/win-capture/get-graphics-offsets/d3d8-offsets.cpp Changed
6
 
1
@@ -1,4 +1,3 @@
2
-#define _CRT_SECURE_NO_WARNINGS
3
 #include <stdio.h>
4
 #include <windows.h>
5
 #include "../d3d8-api/d3d8.h"
6
obs-studio-0.16.6.tar.xz/plugins/win-capture/get-graphics-offsets/d3d9-offsets.cpp -> obs-studio-0.17.0.tar.xz/plugins/win-capture/get-graphics-offsets/d3d9-offsets.cpp Changed
6
 
1
@@ -1,4 +1,3 @@
2
-#define _CRT_SECURE_NO_WARNINGS
3
 #include <stdio.h>
4
 #include <windows.h>
5
 #include <d3d9.h>
6
obs-studio-0.16.6.tar.xz/plugins/win-capture/get-graphics-offsets/dxgi-offsets.cpp -> obs-studio-0.17.0.tar.xz/plugins/win-capture/get-graphics-offsets/dxgi-offsets.cpp Changed
6
 
1
@@ -1,4 +1,3 @@
2
-#define _CRT_SECURE_NO_WARNINGS
3
 #include <windows.h>
4
 #include <d3d10.h>
5
 #include <dxgi.h>
6
obs-studio-0.16.6.tar.xz/plugins/win-capture/get-graphics-offsets/get-graphics-offsets.c -> obs-studio-0.17.0.tar.xz/plugins/win-capture/get-graphics-offsets/get-graphics-offsets.c Changed
6
 
1
@@ -1,4 +1,3 @@
2
-#define _CRT_SECURE_NO_WARNINGS
3
 #include <inttypes.h>
4
 #include <stdio.h>
5
 #include <windows.h>
6
obs-studio-0.16.6.tar.xz/plugins/win-capture/graphics-hook-info.h -> obs-studio-0.17.0.tar.xz/plugins/win-capture/graphics-hook-info.h Changed
59
 
1
@@ -7,19 +7,21 @@
2
 
3
 #include "hook-helpers.h"
4
 
5
-#define EVENT_CAPTURE_RESTART "CaptureHook_Restart"
6
-#define EVENT_CAPTURE_STOP    "CaptureHook_Stop"
7
+#define EVENT_CAPTURE_RESTART L"CaptureHook_Restart"
8
+#define EVENT_CAPTURE_STOP    L"CaptureHook_Stop"
9
 
10
-#define EVENT_HOOK_READY      "CaptureHook_HookReady"
11
-#define EVENT_HOOK_EXIT       "CaptureHook_Exit"
12
+#define EVENT_HOOK_READY      L"CaptureHook_HookReady"
13
+#define EVENT_HOOK_EXIT       L"CaptureHook_Exit"
14
 
15
-#define EVENT_HOOK_KEEPALIVE  "CaptureHook_KeepAlive"
16
+#define EVENT_HOOK_INIT       L"CaptureHook_Initialize"
17
 
18
-#define MUTEX_TEXTURE1        "CaptureHook_TextureMutex1"
19
-#define MUTEX_TEXTURE2        "CaptureHook_TextureMutex2"
20
+#define WINDOW_HOOK_KEEPALIVE L"CaptureHook_KeepAlive"
21
 
22
-#define SHMEM_HOOK_INFO       "Local\\CaptureHook_HookInfo"
23
-#define SHMEM_TEXTURE         "Local\\CaptureHook_Texture"
24
+#define MUTEX_TEXTURE1        L"CaptureHook_TextureMutex1"
25
+#define MUTEX_TEXTURE2        L"CaptureHook_TextureMutex2"
26
+
27
+#define SHMEM_HOOK_INFO       L"CaptureHook_HookInfo"
28
+#define SHMEM_TEXTURE         L"CaptureHook_Texture"
29
 
30
 #define PIPE_NAME             "CaptureHook_Pipe"
31
 
32
@@ -101,19 +103,13 @@
33
 
34
 #pragma pack(pop)
35
 
36
-static inline HANDLE get_hook_info(DWORD id)
37
-{
38
-   HANDLE handle;
39
-   char new_name[64];
40
-   sprintf(new_name, "%s%lu", SHMEM_HOOK_INFO, id);
41
-
42
-   handle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL,
43
-           PAGE_READWRITE, 0, sizeof(struct hook_info), new_name);
44
+#define GC_MAPPING_FLAGS (FILE_MAP_READ | FILE_MAP_WRITE)
45
 
46
-   if (!handle && GetLastError() == ERROR_ALREADY_EXISTS) {
47
-       handle = OpenFileMappingA(FILE_MAP_ALL_ACCESS, false,
48
-               new_name);
49
-   }
50
+static inline HANDLE create_hook_info(DWORD id)
51
+{
52
+   wchar_t new_name[64];
53
+   _snwprintf(new_name, 64, L"%s%lu", SHMEM_HOOK_INFO, id);
54
 
55
-   return handle;
56
+   return CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
57
+           0, sizeof(struct hook_info), new_name);
58
 }
59
obs-studio-0.16.6.tar.xz/plugins/win-capture/graphics-hook/CMakeLists.txt -> obs-studio-0.17.0.tar.xz/plugins/win-capture/graphics-hook/CMakeLists.txt Changed
12
 
1
@@ -29,6 +29,10 @@
2
    d3d11-capture.cpp
3
    d3d12-capture.cpp)
4
 
5
+if(MSVC)
6
+   add_compile_options("$<$<CONFIG:RelWithDebInfo>:/MT>")
7
+endif()
8
+
9
 add_library(graphics-hook MODULE
10
    ${graphics-hook_SOURCES}
11
    ${graphics-hook_HEADERS})
12
obs-studio-0.16.6.tar.xz/plugins/win-capture/graphics-hook/d3d10-capture.cpp -> obs-studio-0.17.0.tar.xz/plugins/win-capture/graphics-hook/d3d10-capture.cpp Changed
15
 
1
@@ -1,4 +1,3 @@
2
-#define _CRT_SECURE_NO_WARNINGS
3
 #include <d3d10.h>
4
 #include <dxgi.h>
5
 
6
@@ -772,7 +771,7 @@
7
    data.cur_tex = next_tex;
8
 }
9
 
10
-void d3d10_capture(void *swap_ptr, void *backbuffer_ptr)
11
+void d3d10_capture(void *swap_ptr, void *backbuffer_ptr, bool)
12
 {
13
    IDXGIResource *dxgi_backbuffer = (IDXGIResource*)backbuffer_ptr;
14
    IDXGISwapChain *swap = (IDXGISwapChain*)swap_ptr;
15
obs-studio-0.16.6.tar.xz/plugins/win-capture/graphics-hook/d3d11-capture.cpp -> obs-studio-0.17.0.tar.xz/plugins/win-capture/graphics-hook/d3d11-capture.cpp Changed
15
 
1
@@ -1,4 +1,3 @@
2
-#define _CRT_SECURE_NO_WARNINGS
3
 #include <d3d11.h>
4
 #include <dxgi.h>
5
 
6
@@ -814,7 +813,7 @@
7
    data.cur_tex = next_tex;
8
 }
9
 
10
-void d3d11_capture(void *swap_ptr, void *backbuffer_ptr)
11
+void d3d11_capture(void *swap_ptr, void *backbuffer_ptr, bool)
12
 {
13
    IDXGIResource *dxgi_backbuffer = (IDXGIResource*)backbuffer_ptr;
14
    IDXGISwapChain *swap = (IDXGISwapChain*)swap_ptr;
15
obs-studio-0.16.6.tar.xz/plugins/win-capture/graphics-hook/d3d12-capture.cpp -> obs-studio-0.17.0.tar.xz/plugins/win-capture/graphics-hook/d3d12-capture.cpp Changed
275
 
1
@@ -1,4 +1,3 @@
2
-#define _CRT_SECURE_NO_WARNINGS
3
 #include <windows.h>
4
 #include "graphics-hook.h"
5
 
6
@@ -6,11 +5,13 @@
7
 
8
 #include <d3d11on12.h>
9
 #include <d3d12.h>
10
-#include <dxgi1_2.h>
11
+#include <dxgi1_4.h>
12
 
13
 #include "dxgi-helpers.hpp"
14
 #include "../funchook.h"
15
 
16
+#define MAX_BACKBUFFERS 8
17
+
18
 struct d3d12_data {
19
    ID3D12Device                   *device; /* do not release */
20
    uint32_t                       base_cx;
21
@@ -21,6 +22,7 @@
22
    bool                           using_shtex : 1;
23
    bool                           using_scale : 1;
24
    bool                           multisampled : 1;
25
+   bool                           dxgi_1_4 : 1;
26
 
27
    ID3D11Device                   *device11;
28
    ID3D11DeviceContext            *context11;
29
@@ -29,7 +31,9 @@
30
    union {
31
        struct {
32
            struct shtex_data      *shtex_info;
33
-           ID3D11Resource         *backbuffer11;
34
+           ID3D11Resource         *backbuffer11[MAX_BACKBUFFERS];
35
+           UINT                   backbuffer_count;
36
+           UINT                   cur_backbuffer;
37
            ID3D11Texture2D        *copy_tex;
38
            HANDLE                 handle;
39
        };
40
@@ -42,8 +46,10 @@
41
 {
42
    if (data.copy_tex)
43
        data.copy_tex->Release();
44
-   if (data.backbuffer11)
45
-       data.backbuffer11->Release();
46
+   for (size_t i = 0; i < data.backbuffer_count; i++) {
47
+       if (data.backbuffer11[i])
48
+           data.backbuffer11[i]->Release();
49
+   }
50
    if (data.device11)
51
        data.device11->Release();
52
    if (data.context11)
53
@@ -58,20 +64,34 @@
54
    hlog("----------------- d3d12 capture freed ----------------");
55
 }
56
 
57
-static bool create_d3d12_tex(ID3D12Resource *backbuffer)
58
+struct bb_info {
59
+   ID3D12Resource *backbuffer[MAX_BACKBUFFERS];
60
+   UINT count;
61
+};
62
+
63
+static bool create_d3d12_tex(bb_info &bb)
64
 {
65
    D3D11_RESOURCE_FLAGS rf11 = {};
66
    HRESULT hr;
67
 
68
-   hr = data.device11on12->CreateWrappedResource(backbuffer, &rf11,
69
-           D3D12_RESOURCE_STATE_COPY_SOURCE,
70
-           D3D12_RESOURCE_STATE_PRESENT,
71
-           __uuidof(ID3D11Resource),
72
-           (void**)&data.backbuffer11);
73
-   if (FAILED(hr)) {
74
-       hlog_hr("create_d3d12_tex: failed to create backbuffer11",
75
-               hr);
76
+   if (!bb.count)
77
        return false;
78
+
79
+   data.backbuffer_count = bb.count;
80
+
81
+   for (UINT i = 0; i < bb.count; i++) {
82
+       hr = data.device11on12->CreateWrappedResource(
83
+               bb.backbuffer[i],
84
+               &rf11,
85
+               D3D12_RESOURCE_STATE_COPY_SOURCE,
86
+               D3D12_RESOURCE_STATE_PRESENT,
87
+               __uuidof(ID3D11Resource),
88
+               (void**)&data.backbuffer11[i]);
89
+       if (FAILED(hr)) {
90
+           hlog_hr("create_d3d12_tex: failed to create "
91
+                   "backbuffer11", hr);
92
+           return false;
93
+       }
94
    }
95
 
96
    D3D11_TEXTURE2D_DESC desc11 = {};
97
@@ -91,7 +111,10 @@
98
        return false;
99
    }
100
 
101
-   data.device11on12->ReleaseWrappedResources(&data.backbuffer11, 1);
102
+   for (UINT i = 0; i < bb.count; i++) {
103
+       data.device11on12->ReleaseWrappedResources(
104
+               &data.backbuffer11[i], 1);
105
+   }
106
 
107
    IDXGIResource *dxgi_res;
108
    hr = data.copy_tex->QueryInterface(__uuidof(IDXGIResource),
109
@@ -175,12 +198,12 @@
110
    return true;
111
 }
112
 
113
-static bool d3d12_shtex_init(HWND window, ID3D12Resource *backbuffer)
114
+static bool d3d12_shtex_init(HWND window, bb_info &bb)
115
 {
116
    if (!d3d12_init_11on12()) {
117
        return false;
118
    }
119
-   if (!create_d3d12_tex(backbuffer)) {
120
+   if (!create_d3d12_tex(bb)) {
121
        return false;
122
    }
123
    if (!capture_init_shtex(&data.shtex_info, window,
124
@@ -193,9 +216,11 @@
125
    return true;
126
 }
127
 
128
-static inline bool d3d12_init_format(IDXGISwapChain *swap, HWND &window)
129
+static inline bool d3d12_init_format(IDXGISwapChain *swap, HWND &window,
130
+       bb_info &bb)
131
 {
132
    DXGI_SWAP_CHAIN_DESC desc;
133
+   IDXGISwapChain3 *swap3;
134
    HRESULT hr;
135
 
136
    hr = swap->GetDesc(&desc);
137
@@ -210,6 +235,39 @@
138
    data.base_cx = desc.BufferDesc.Width;
139
    data.base_cy = desc.BufferDesc.Height;
140
 
141
+   hr = swap->QueryInterface(__uuidof(IDXGISwapChain3), (void**)&swap3);
142
+   if (SUCCEEDED(hr)) {
143
+       data.dxgi_1_4 = true;
144
+       hlog("We're DXGI1.4 boys!");
145
+       swap3->Release();
146
+   }
147
+
148
+   hlog("Buffer count: %d, swap effect: %d", (int)desc.BufferCount,
149
+           (int)desc.SwapEffect);
150
+
151
+   bb.count = desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD
152
+       ? 1 : desc.BufferCount;
153
+
154
+   if (bb.count == 1)
155
+       data.dxgi_1_4 = false;
156
+
157
+   if (bb.count > MAX_BACKBUFFERS) {
158
+       hlog("Somehow it's using more than the max backbuffers.  "
159
+               "Not sure why anyone would do that.");
160
+       bb.count = 1;
161
+       data.dxgi_1_4 = false;
162
+   }
163
+
164
+   for (UINT i = 0; i < bb.count; i++) {
165
+       hr = swap->GetBuffer(i, __uuidof(ID3D12Resource),
166
+               (void**)&bb.backbuffer[i]);
167
+       if (SUCCEEDED(hr)) {
168
+           bb.backbuffer[i]->Release();
169
+       } else {
170
+           return false;
171
+       }
172
+   }
173
+
174
    if (data.using_scale) {
175
        data.cx = global_hook_info->cx;
176
        data.cy = global_hook_info->cy;
177
@@ -220,9 +278,10 @@
178
    return true;
179
 }
180
 
181
-static void d3d12_init(IDXGISwapChain *swap, ID3D12Resource *backbuffer)
182
+static void d3d12_init(IDXGISwapChain *swap)
183
 {
184
    bool success = true;
185
+   bb_info bb = {};
186
    HWND window;
187
    HRESULT hr;
188
 
189
@@ -236,7 +295,7 @@
190
 
191
    data.device->Release();
192
 
193
-   if (!d3d12_init_format(swap, window)) {
194
+   if (!d3d12_init_format(swap, window, bb)) {
195
        return;
196
    }
197
    if (data.using_scale) {
198
@@ -248,7 +307,7 @@
199
                    "unsupported; ignoring");
200
        }
201
 
202
-       success = d3d12_shtex_init(window, backbuffer);
203
+       success = d3d12_shtex_init(window, bb);
204
    }
205
 
206
    if (!success)
207
@@ -264,37 +323,49 @@
208
    }
209
 }
210
 
211
-static inline void d3d12_shtex_capture()
212
+static inline void d3d12_shtex_capture(IDXGISwapChain *swap,
213
+       bool capture_overlay)
214
 {
215
-   data.device11on12->AcquireWrappedResources(&data.backbuffer11, 1);
216
-   d3d12_copy_texture(data.copy_tex, data.backbuffer11);
217
-   data.device11on12->ReleaseWrappedResources(&data.backbuffer11, 1);
218
+   bool dxgi_1_4 = data.dxgi_1_4;
219
+   UINT cur_idx;
220
+
221
+   if (dxgi_1_4) {
222
+       IDXGISwapChain3 *swap3 =
223
+           reinterpret_cast<IDXGISwapChain3*>(swap);
224
+       cur_idx = swap3->GetCurrentBackBufferIndex();
225
+       if (!capture_overlay) {
226
+           if (++cur_idx >= data.backbuffer_count)
227
+               cur_idx = 0;
228
+       }
229
+   } else {
230
+       cur_idx = data.cur_backbuffer;
231
+   }
232
+
233
+   ID3D11Resource *backbuffer = data.backbuffer11[cur_idx];
234
+
235
+   data.device11on12->AcquireWrappedResources(&backbuffer, 1);
236
+   d3d12_copy_texture(data.copy_tex, backbuffer);
237
+   data.device11on12->ReleaseWrappedResources(&backbuffer, 1);
238
    data.context11->Flush();
239
+
240
+   if (!dxgi_1_4) {
241
+       if (++data.cur_backbuffer >= data.backbuffer_count)
242
+           data.cur_backbuffer = 0;
243
+   }
244
 }
245
 
246
-void d3d12_capture(void *swap_ptr, void *backbuffer_ptr)
247
+void d3d12_capture(void *swap_ptr, void*, bool capture_overlay)
248
 {
249
-   IUnknown *unk_backbuffer = (IUnknown*)backbuffer_ptr;
250
    IDXGISwapChain *swap = (IDXGISwapChain*)swap_ptr;
251
-   ID3D12Resource *backbuffer;
252
-   HRESULT hr;
253
 
254
    if (capture_should_stop()) {
255
        d3d12_free();
256
    }
257
    if (capture_should_init()) {
258
-       hr = unk_backbuffer->QueryInterface(__uuidof(ID3D12Resource),
259
-               (void**)&backbuffer);
260
-       if (FAILED(hr)) {
261
-           hlog_hr("d3d12_capture: failed to get backbuffer", hr);
262
-           return;
263
-       }
264
-
265
-       d3d12_init(swap, backbuffer);
266
-       backbuffer->Release();
267
+       d3d12_init(swap);
268
    }
269
    if (capture_ready()) {
270
-       d3d12_shtex_capture();
271
+       d3d12_shtex_capture(swap, capture_overlay);
272
    }
273
 }
274
 
275
obs-studio-0.16.6.tar.xz/plugins/win-capture/graphics-hook/d3d8-capture.cpp -> obs-studio-0.17.0.tar.xz/plugins/win-capture/graphics-hook/d3d8-capture.cpp Changed
6
 
1
@@ -1,4 +1,3 @@
2
-#define _CRT_SECURE_NO_WARNINGS
3
 #include <dxgi.h>
4
 
5
 #include "../d3d8-api/d3d8.h"
6
obs-studio-0.16.6.tar.xz/plugins/win-capture/graphics-hook/d3d9-capture.cpp -> obs-studio-0.17.0.tar.xz/plugins/win-capture/graphics-hook/d3d9-capture.cpp Changed
6
 
1
@@ -1,4 +1,3 @@
2
-#define _CRT_SECURE_NO_WARNINGS
3
 #include <d3d9.h>
4
 #include <d3d11.h>
5
 #include <dxgi.h>
6
obs-studio-0.16.6.tar.xz/plugins/win-capture/graphics-hook/dxgi-capture.cpp -> obs-studio-0.17.0.tar.xz/plugins/win-capture/graphics-hook/dxgi-capture.cpp Changed
33
 
1
@@ -1,4 +1,3 @@
2
-#define _CRT_SECURE_NO_WARNINGS
3
 #include <d3d10_1.h>
4
 #include <d3d11.h>
5
 #include <dxgi.h>
6
@@ -21,7 +20,7 @@
7
 
8
 struct dxgi_swap_data {
9
    IDXGISwapChain *swap;
10
-   void (*capture)(void*, void*);
11
+   void (*capture)(void*, void*, bool);
12
    void (*free)(void);
13
 };
14
 
15
@@ -132,7 +131,7 @@
16
        backbuffer = get_dxgi_backbuffer(swap);
17
 
18
        if (!!backbuffer) {
19
-           data.capture(swap, backbuffer);
20
+           data.capture(swap, backbuffer, capture_overlay);
21
            backbuffer->Release();
22
        }
23
    }
24
@@ -156,7 +155,7 @@
25
            backbuffer = get_dxgi_backbuffer(swap);
26
 
27
            if (!!backbuffer) {
28
-               data.capture(swap, backbuffer);
29
+               data.capture(swap, backbuffer, capture_overlay);
30
                backbuffer->Release();
31
            }
32
        }
33
obs-studio-0.16.6.tar.xz/plugins/win-capture/graphics-hook/gl-capture.c -> obs-studio-0.17.0.tar.xz/plugins/win-capture/graphics-hook/gl-capture.c Changed
7
 
1
@@ -1,5 +1,3 @@
2
-#define _CRT_SECURE_NO_WARNINGS
3
-
4
 #ifdef _MSC_VER
5
 #pragma warning(disable : 4214) /* nonstandard extension, non-int bitfield */
6
 #pragma warning(disable : 4054) /* function pointer to data pointer */
7
obs-studio-0.16.6.tar.xz/plugins/win-capture/graphics-hook/graphics-hook.c -> obs-studio-0.17.0.tar.xz/plugins/win-capture/graphics-hook/graphics-hook.c Changed
168
 
1
@@ -1,4 +1,3 @@
2
-#define _CRT_SECURE_NO_WARNINGS
3
 #include <windows.h>
4
 #include <psapi.h>
5
 #include "graphics-hook.h"
6
@@ -32,6 +31,7 @@
7
 HANDLE                         signal_stop                     = NULL;
8
 HANDLE                         signal_ready                    = NULL;
9
 HANDLE                         signal_exit                     = NULL;
10
+static HANDLE                  signal_init                     = NULL;
11
 HANDLE                         tex_mutexes[2]                  = {NULL, NULL};
12
 static HANDLE                  filemap_hook_info               = NULL;
13
 
14
@@ -40,7 +40,7 @@
15
 static HANDLE                  capture_thread                  = NULL;
16
 char                           system_path[MAX_PATH]           = {0};
17
 char                           process_name[MAX_PATH]          = {0};
18
-char                           keepalive_name[64]              = {0};
19
+wchar_t                        keepalive_name[64]              = {0};
20
 HWND                           dummy_window                    = NULL;
21
 
22
 static unsigned int            shmem_id_counter                = 0;
23
@@ -74,22 +74,17 @@
24
    return true;
25
 }
26
 
27
-static HANDLE init_event(const char *name, DWORD pid)
28
+static HANDLE init_event(const wchar_t *name, DWORD pid)
29
 {
30
-   HANDLE handle = get_event_plus_id(name, pid);
31
+   HANDLE handle = create_event_plus_id(name, pid);
32
    if (!handle)
33
        hlog("Failed to get event '%s': %lu", name, GetLastError());
34
    return handle;
35
 }
36
 
37
-static HANDLE init_mutex(const char *name, DWORD pid)
38
+static HANDLE init_mutex(const wchar_t *name, DWORD pid)
39
 {
40
-   char new_name[64];
41
-   HANDLE handle;
42
-
43
-   sprintf(new_name, "%s%lu", name, pid);
44
-
45
-   handle = OpenMutexA(MUTEX_ALL_ACCESS, false, new_name);
46
+   HANDLE handle = create_mutex_plus_id(name, pid);
47
    if (!handle)
48
        hlog("Failed to open mutex '%s': %lu", name, GetLastError());
49
    return handle;
50
@@ -119,6 +114,11 @@
51
        return false;
52
    }
53
 
54
+   signal_init = init_event(EVENT_HOOK_INIT, pid);
55
+   if (!signal_init) {
56
+       return false;
57
+   }
58
+
59
    return true;
60
 }
61
 
62
@@ -164,7 +164,7 @@
63
 
64
 static inline bool init_hook_info(void)
65
 {
66
-   filemap_hook_info = get_hook_info(GetCurrentProcessId());
67
+   filemap_hook_info = create_hook_info(GetCurrentProcessId());
68
    if (!filemap_hook_info) {
69
        hlog("Failed to create hook info file mapping: %lu",
70
                GetLastError());
71
@@ -235,24 +235,10 @@
72
 {
73
    wait_for_dll_main_finish(thread_handle);
74
 
75
-   sprintf(keepalive_name, "%s%lu", EVENT_HOOK_KEEPALIVE,
76
-           GetCurrentProcessId());
77
+   _snwprintf(keepalive_name, sizeof(keepalive_name), L"%s%lu",
78
+           WINDOW_HOOK_KEEPALIVE, GetCurrentProcessId());
79
 
80
-   if (!init_pipe()) {
81
-       return false;
82
-   }
83
-   if (!init_signals()) {
84
-       return false;
85
-   }
86
-   if (!init_mutexes()) {
87
-       return false;
88
-   }
89
-   if (!init_system_path()) {
90
-       return false;
91
-   }
92
-   if (!init_hook_info()) {
93
-       return false;
94
-   }
95
+   init_pipe();
96
 
97
    init_dummy_window_thread();
98
    log_current_process();
99
@@ -329,6 +315,7 @@
100
 
101
    if (!d3d9_hooked) {
102
        if (!d3d9_hookable()) {
103
+           DbgOut("no D3D9 hook address found!\n");
104
            d3d9_hooked = true;
105
        } else {
106
            d3d9_hooked = hook_d3d9();
107
@@ -340,6 +327,7 @@
108
 
109
    if (!dxgi_hooked) {
110
        if (!dxgi_hookable()) {
111
+           DbgOut("no DXGI hook address found!\n");
112
            dxgi_hooked = true;
113
        } else {
114
            dxgi_hooked = hook_dxgi();
115
@@ -385,6 +373,8 @@
116
 
117
 static inline void capture_loop(void)
118
 {
119
+   WaitForSingleObject(signal_init, INFINITE);
120
+
121
    while (!attempt_hook())
122
        Sleep(40);
123
 
124
@@ -496,10 +486,10 @@
125
 
126
 static inline bool init_shared_info(size_t size)
127
 {
128
-   char name[64];
129
-   sprintf_s(name, 64, "%s%u", SHMEM_TEXTURE, ++shmem_id_counter);
130
+   wchar_t name[64];
131
+   _snwprintf(name, 64, L"%s%ld", SHMEM_TEXTURE, ++shmem_id_counter);
132
 
133
-   shmem_file_handle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL,
134
+   shmem_file_handle = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
135
            PAGE_READWRITE, 0, (DWORD)size, name);
136
    if (!shmem_file_handle) {
137
        hlog("init_shared_info: Failed to create shared memory: %d",
138
@@ -792,8 +782,27 @@
139
 
140
        dll_inst = hinst;
141
 
142
-       HANDLE cur_thread = OpenThread(THREAD_ALL_ACCESS, false,
143
-               GetCurrentThreadId());
144
+       HANDLE cur_thread;
145
+       bool success = DuplicateHandle(GetCurrentProcess(),
146
+               GetCurrentThread(),
147
+               GetCurrentProcess(), &cur_thread,
148
+               SYNCHRONIZE, false, 0);
149
+
150
+       if (!success)
151
+           DbgOut("Failed to get current thread handle");
152
+
153
+       if (!init_signals()) {
154
+           return false;
155
+       }
156
+       if (!init_system_path()) {
157
+           return false;
158
+       }
159
+       if (!init_hook_info()) {
160
+           return false;
161
+       }
162
+       if (!init_mutexes()) {
163
+           return false;
164
+       }
165
 
166
        /* this prevents the library from being automatically unloaded
167
         * by the next FreeLibrary call */
168
obs-studio-0.16.6.tar.xz/plugins/win-capture/graphics-hook/graphics-hook.h -> obs-studio-0.17.0.tar.xz/plugins/win-capture/graphics-hook/graphics-hook.h Changed
63
 
1
@@ -43,13 +43,13 @@
2
 extern bool hook_dxgi(void);
3
 extern bool hook_gl(void);
4
 
5
-extern void d3d10_capture(void *swap, void *backbuffer);
6
+extern void d3d10_capture(void *swap, void *backbuffer, bool capture_overlay);
7
 extern void d3d10_free(void);
8
-extern void d3d11_capture(void *swap, void *backbuffer);
9
+extern void d3d11_capture(void *swap, void *backbuffer, bool capture_overlay);
10
 extern void d3d11_free(void);
11
 
12
 #if COMPILE_D3D12_HOOK
13
-extern void d3d12_capture(void *swap, void *backbuffer);
14
+extern void d3d12_capture(void *swap, void *backbuffer, bool capture_overlay);
15
 extern void d3d12_free(void);
16
 #endif
17
 
18
@@ -98,7 +98,7 @@
19
 extern HANDLE tex_mutexes[2];
20
 extern char system_path[MAX_PATH];
21
 extern char process_name[MAX_PATH];
22
-extern char keepalive_name[64];
23
+extern wchar_t keepalive_name[64];
24
 extern HWND dummy_window;
25
 extern volatile bool active;
26
 
27
@@ -143,13 +143,7 @@
28
 
29
 static inline bool capture_alive(void)
30
 {
31
-   HANDLE event = OpenEventA(EVENT_ALL_ACCESS, false, keepalive_name);
32
-   if (event) {
33
-       CloseHandle(event);
34
-       return true;
35
-   }
36
-
37
-   return false;
38
+   return !!FindWindowW(keepalive_name, NULL);
39
 }
40
 
41
 static inline bool capture_active(void)
42
@@ -198,8 +192,18 @@
43
 {
44
    bool stop_requested = false;
45
 
46
-   if (capture_active())
47
-       stop_requested = capture_stopped() || !capture_alive();
48
+   if (capture_active()) {
49
+       static uint64_t last_keepalive_check = 0;
50
+       uint64_t cur_time = os_gettime_ns();
51
+       bool alive = true;
52
+
53
+       if (cur_time - last_keepalive_check > 5000000000) {
54
+           alive = capture_alive();
55
+           last_keepalive_check = cur_time;
56
+       }
57
+
58
+       stop_requested = capture_stopped() || !alive;
59
+   }
60
 
61
    return stop_requested;
62
 }
63
obs-studio-0.16.6.tar.xz/plugins/win-capture/hook-helpers.h -> obs-studio-0.17.0.tar.xz/plugins/win-capture/hook-helpers.h Changed
61
 
1
@@ -4,36 +4,41 @@
2
 #define inline __inline
3
 #endif
4
 
5
-static inline HANDLE get_event(const char *name)
6
+#define GC_EVENT_FLAGS (EVENT_MODIFY_STATE | SYNCHRONIZE)
7
+#define GC_MUTEX_FLAGS (SYNCHRONIZE)
8
+
9
+static inline HANDLE create_event(const wchar_t *name)
10
 {
11
-   HANDLE event = CreateEventA(NULL, false, false, name);
12
-   if (!event)
13
-       event = OpenEventA(EVENT_ALL_ACCESS, false, name);
14
+   return CreateEventW(NULL, false, false, name);
15
+}
16
 
17
-   return event;
18
+static inline HANDLE open_event(const wchar_t *name)
19
+{
20
+   return OpenEventW(GC_EVENT_FLAGS, false, name);
21
 }
22
 
23
-static inline HANDLE get_mutex(const char *name)
24
+static inline HANDLE create_mutex(const wchar_t *name)
25
 {
26
-   HANDLE event = CreateMutexA(NULL, false, name);
27
-   if (!event)
28
-       event = OpenMutexA(MUTEX_ALL_ACCESS, false, name);
29
+   return CreateMutexW(NULL, false, name);
30
+}
31
 
32
-   return event;
33
+static inline HANDLE open_mutex(const wchar_t *name)
34
+{
35
+   return OpenMutexW(GC_MUTEX_FLAGS, false, name);
36
 }
37
 
38
-static inline HANDLE get_event_plus_id(const char *name, DWORD id)
39
+static inline HANDLE create_event_plus_id(const wchar_t *name, DWORD id)
40
 {
41
-   char new_name[64];
42
-   sprintf(new_name, "%s%lu", name, id);
43
-   return get_event(new_name);
44
+   wchar_t new_name[64];
45
+   _snwprintf(new_name, 64, L"%s%lu", name, id);
46
+   return create_event(new_name);
47
 }
48
 
49
-static inline HANDLE get_mutex_plus_id(const char *name, DWORD id)
50
+static inline HANDLE create_mutex_plus_id(const wchar_t *name, DWORD id)
51
 {
52
-   char new_name[64];
53
-   sprintf(new_name, "%s%lu", name, id);
54
-   return get_mutex(new_name);
55
+   wchar_t new_name[64];
56
+   _snwprintf(new_name, 64, L"%s%lu", name, id);
57
+   return create_mutex(new_name);
58
 }
59
 
60
 static inline bool object_signalled(HANDLE event)
61
obs-studio-0.16.6.tar.xz/plugins/win-capture/inject-helper/CMakeLists.txt -> obs-studio-0.17.0.tar.xz/plugins/win-capture/inject-helper/CMakeLists.txt Changed
12
 
1
@@ -9,6 +9,10 @@
2
    ../obfuscate.c
3
    inject-helper.c)
4
 
5
+if(MSVC)
6
+   add_compile_options("$<$<CONFIG:RelWithDebInfo>:/MT>")
7
+endif()
8
+
9
 add_executable(inject-helper
10
    ${inject-helper_SOURCES})
11
 
12
obs-studio-0.16.6.tar.xz/plugins/win-capture/inject-helper/inject-helper.c -> obs-studio-0.17.0.tar.xz/plugins/win-capture/inject-helper/inject-helper.c Changed
7
 
1
@@ -1,5 +1,3 @@
2
-#define _CRT_SECURE_NO_WARNINGS
3
-
4
 #include <stdio.h>
5
 #include <stdlib.h>
6
 #include <wchar.h>
7
obs-studio-0.16.6.tar.xz/plugins/win-capture/load-graphics-offsets.c -> obs-studio-0.17.0.tar.xz/plugins/win-capture/load-graphics-offsets.c Changed
6
 
1
@@ -1,4 +1,3 @@
2
-#define _CRT_SECURE_NO_WARNINGS
3
 #include <obs-module.h>
4
 #include <util/windows/win-version.h>
5
 #include <util/platform.h>
6
obs-studio-0.17.0.tar.xz/plugins/win-capture/nt-stuff.h Added
207
 
1
@@ -0,0 +1,205 @@
2
+#pragma once
3
+
4
+#include <winternl.h>
5
+
6
+#define THREAD_STATE_WAITING 5
7
+#define THREAD_WAIT_REASON_SUSPENDED 5
8
+
9
+typedef struct _SYSTEM_PROCESS_INFORMATION2 {
10
+    ULONG NextEntryOffset;
11
+    ULONG ThreadCount;
12
+    BYTE Reserved1[48];
13
+    PVOID Reserved2[3];
14
+    HANDLE UniqueProcessId;
15
+    PVOID Reserved3;
16
+    ULONG HandleCount;
17
+    BYTE Reserved4[4];
18
+    PVOID Reserved5[11];
19
+    SIZE_T PeakPagefileUsage;
20
+    SIZE_T PrivatePageCount;
21
+    LARGE_INTEGER Reserved6[6];
22
+} SYSTEM_PROCESS_INFORMATION2;
23
+
24
+typedef struct _SYSTEM_THREAD_INFORMATION {
25
+   FILETIME KernelTime;
26
+   FILETIME UserTime;
27
+   FILETIME CreateTime;
28
+   DWORD WaitTime;
29
+   PVOID Address;
30
+   HANDLE UniqueProcessId;
31
+   HANDLE UniqueThreadId;
32
+   DWORD Priority;
33
+   DWORD BasePriority;
34
+   DWORD ContextSwitches;
35
+   DWORD ThreadState;
36
+   DWORD WaitReason;
37
+   DWORD Reserved1;
38
+} SYSTEM_THREAD_INFORMATION;
39
+
40
+#ifndef NT_SUCCESS
41
+#define NT_SUCCESS(status) ((NTSTATUS)(status) >= 0)
42
+#endif
43
+
44
+#define STATUS_INFO_LENGTH_MISMATCH      ((NTSTATUS)0xC0000004L)
45
+
46
+#define init_named_attribs(o, name) \
47
+   do { \
48
+       (o)->Length = sizeof(*(o)); \
49
+       (o)->ObjectName = name; \
50
+       (o)->RootDirectory = NULL; \
51
+       (o)->Attributes = 0; \
52
+       (o)->SecurityDescriptor = NULL; \
53
+       (o)->SecurityQualityOfService = NULL; \
54
+   } while (false)
55
+
56
+typedef void (WINAPI *RTLINITUNICODESTRINGFUNC)(PCUNICODE_STRING pstr, const wchar_t *lpstrName);
57
+typedef NTSTATUS (WINAPI *NTOPENFUNC)(PHANDLE phandle, ACCESS_MASK access, POBJECT_ATTRIBUTES objattr);
58
+typedef ULONG (WINAPI *RTLNTSTATUSTODOSERRORFUNC)(NTSTATUS status);
59
+typedef NTSTATUS (WINAPI *NTQUERYSYSTEMINFORMATIONFUNC)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
60
+
61
+static FARPROC get_nt_func(const char *name)
62
+{
63
+   static bool initialized = false;
64
+   static HANDLE ntdll = NULL;
65
+   if (!initialized) {
66
+       ntdll = GetModuleHandleW(L"ntdll");
67
+       initialized = true;
68
+   }
69
+
70
+   return GetProcAddress(ntdll, name);
71
+}
72
+
73
+static void nt_set_last_error(NTSTATUS status)
74
+{
75
+   static bool initialized = false;
76
+   static RTLNTSTATUSTODOSERRORFUNC func = NULL;
77
+
78
+   if (!initialized) {
79
+       func = (RTLNTSTATUSTODOSERRORFUNC)get_nt_func(
80
+               "RtlNtStatusToDosError");
81
+       initialized = true;
82
+   }
83
+
84
+   if (func)
85
+       SetLastError(func(status));
86
+}
87
+
88
+static void rtl_init_str(UNICODE_STRING *unistr, const wchar_t *str)
89
+{
90
+   static bool initialized = false;
91
+   static RTLINITUNICODESTRINGFUNC func = NULL;
92
+
93
+   if (!initialized) {
94
+       func = (RTLINITUNICODESTRINGFUNC)get_nt_func(
95
+               "RtlInitUnicodeString");
96
+       initialized = true;
97
+   }
98
+
99
+   if (func)
100
+       func(unistr, str);
101
+}
102
+
103
+static NTSTATUS nt_query_information(SYSTEM_INFORMATION_CLASS info_class,
104
+       PVOID info, ULONG info_len, PULONG ret_len)
105
+{
106
+   static bool initialized = false;
107
+   static NTQUERYSYSTEMINFORMATIONFUNC func = NULL;
108
+
109
+   if (!initialized) {
110
+       func = (NTQUERYSYSTEMINFORMATIONFUNC)get_nt_func(
111
+               "NtQuerySystemInformation");
112
+       initialized = true;
113
+   }
114
+
115
+   if (func)
116
+       return func(info_class, info, info_len, ret_len);
117
+   return (NTSTATUS)-1;
118
+}
119
+
120
+static bool thread_is_suspended(DWORD process_id, DWORD thread_id)
121
+{
122
+   ULONG size = 4096;
123
+   bool suspended = false;
124
+   void *data = malloc(size);
125
+
126
+   for (;;) {
127
+       NTSTATUS stat = nt_query_information(SystemProcessInformation,
128
+               data, size, &size);
129
+       if (NT_SUCCESS(stat))
130
+           break;
131
+
132
+       if (stat != STATUS_INFO_LENGTH_MISMATCH) {
133
+           goto fail;
134
+       }
135
+
136
+       free(data);
137
+       size += 1024;
138
+       data = malloc(size);
139
+   }
140
+
141
+   SYSTEM_PROCESS_INFORMATION2 *spi = data;
142
+
143
+   for (;;) {
144
+       if (spi->UniqueProcessId == (HANDLE)process_id) {
145
+           break;
146
+       }
147
+
148
+       ULONG offset = spi->NextEntryOffset;
149
+       if (!offset)
150
+           goto fail;
151
+
152
+       spi = (SYSTEM_PROCESS_INFORMATION2*)((BYTE*)spi + offset);
153
+   }
154
+
155
+   SYSTEM_THREAD_INFORMATION *sti;
156
+   SYSTEM_THREAD_INFORMATION *info = NULL;
157
+   sti = (SYSTEM_THREAD_INFORMATION*)((BYTE*)spi + sizeof(*spi));
158
+
159
+   for (ULONG i = 0; i < spi->ThreadCount; i++) {
160
+       if (sti[i].UniqueThreadId == (HANDLE)thread_id) {
161
+           info = &sti[i];
162
+           break;
163
+       }
164
+   }
165
+
166
+   if (info) {
167
+       suspended = info->ThreadState == THREAD_STATE_WAITING &&
168
+           info->WaitReason == THREAD_WAIT_REASON_SUSPENDED;
169
+   }
170
+
171
+fail:
172
+   free(data);
173
+   return suspended;
174
+}
175
+
176
+#define MAKE_NT_OPEN_FUNC(func_name, nt_name, access) \
177
+static HANDLE func_name(const wchar_t *name) \
178
+{ \
179
+   static bool initialized = false; \
180
+   static NTOPENFUNC open = NULL; \
181
+   HANDLE handle; \
182
+   NTSTATUS status; \
183
+   UNICODE_STRING unistr; \
184
+   OBJECT_ATTRIBUTES attr; \
185
+\
186
+   if (!initialized) { \
187
+       open = (NTOPENFUNC)get_nt_func(#nt_name); \
188
+       initialized = true; \
189
+   } \
190
+\
191
+   if (!open) \
192
+       return NULL; \
193
+\
194
+   rtl_init_str(&unistr, name); \
195
+   init_named_attribs(&attr, &unistr); \
196
+\
197
+   status = open(&handle, access, &attr); \
198
+   if (NT_SUCCESS(status)) \
199
+       return handle; \
200
+   nt_set_last_error(status); \
201
+   return NULL; \
202
+}
203
+
204
+MAKE_NT_OPEN_FUNC(nt_open_mutex, NtOpenMutant, SYNCHRONIZE)
205
+MAKE_NT_OPEN_FUNC(nt_open_event, NtOpenEvent, EVENT_MODIFY_STATE | SYNCHRONIZE)
206
+MAKE_NT_OPEN_FUNC(nt_open_map, NtOpenSection, FILE_MAP_READ | FILE_MAP_WRITE)
207
obs-studio-0.16.6.tar.xz/plugins/win-capture/obfuscate.c -> obs-studio-0.17.0.tar.xz/plugins/win-capture/obfuscate.c Changed
7
 
1
@@ -1,5 +1,3 @@
2
-#define _CRT_SECURE_NO_WARNINGS
3
-
4
 #ifdef _MSC_VER
5
 #pragma warning(disable : 4152) /* casting func ptr to void */
6
 #endif
7
obs-studio-0.16.6.tar.xz/plugins/win-capture/window-helpers.c -> obs-studio-0.17.0.tar.xz/plugins/win-capture/window-helpers.c Changed
210
 
1
@@ -128,6 +128,33 @@
2
        dstr_from_wcs(class, temp);
3
 }
4
 
5
+/* not capturable or internal windows */
6
+static const char *internal_microsoft_exes[] = {
7
+   "applicationframehost",
8
+   "shellexperiencehost",
9
+   "winstore.app",
10
+   "searchui",
11
+   NULL
12
+};
13
+
14
+static bool is_microsoft_internal_window_exe(const char *exe)
15
+{
16
+   char cur_exe[MAX_PATH];
17
+
18
+   if (!exe)
19
+       return false;
20
+
21
+   for (const char **vals = internal_microsoft_exes; *vals; vals++) {
22
+       strcpy(cur_exe, *vals);
23
+       strcat(cur_exe, ".exe");
24
+
25
+       if (strcmpi(cur_exe, exe) == 0)
26
+           return true;
27
+   }
28
+
29
+   return false;
30
+}
31
+
32
 static void add_window(obs_property_t *p, HWND hwnd, add_window_cb callback)
33
 {
34
    struct dstr class   = {0};
35
@@ -138,6 +165,10 @@
36
 
37
    if (!get_window_exe(&exe, hwnd))
38
        return;
39
+   if (is_microsoft_internal_window_exe(exe.array)) {
40
+       dstr_free(&exe);
41
+       return;
42
+   }
43
    get_window_title(&title, hwnd);
44
    get_window_class(&class, hwnd);
45
 
46
@@ -192,33 +223,92 @@
47
    return true;
48
 }
49
 
50
-static inline HWND next_window(HWND window, enum window_search_mode mode)
51
+bool is_uwp_window(HWND hwnd)
52
+{
53
+   wchar_t name[256];
54
+
55
+   name[0] = 0;
56
+   if (!GetClassNameW(hwnd, name, sizeof(name) / sizeof(wchar_t)))
57
+       return false;
58
+
59
+   return wcscmp(name, L"ApplicationFrameWindow") == 0;
60
+}
61
+
62
+HWND get_uwp_actual_window(HWND parent)
63
+{
64
+   DWORD parent_id = 0;
65
+   HWND child;
66
+
67
+   GetWindowThreadProcessId(parent, &parent_id);
68
+   child = FindWindowEx(parent, NULL, NULL, NULL);
69
+
70
+   while (child) {
71
+       DWORD child_id = 0;
72
+       GetWindowThreadProcessId(child, &child_id);
73
+
74
+       if (child_id != parent_id)
75
+           return child;
76
+
77
+       child = FindWindowEx(parent, child, NULL, NULL);
78
+   }
79
+
80
+   return NULL;
81
+}
82
+
83
+static inline HWND next_window(HWND window, enum window_search_mode mode,
84
+       HWND *parent)
85
 {
86
+   if (*parent) {
87
+       window = *parent;
88
+       *parent = NULL;
89
+   }
90
+
91
    while (true) {
92
-       window = GetNextWindow(window, GW_HWNDNEXT);
93
+       window = FindWindowEx(GetDesktopWindow(), window, NULL, NULL);
94
        if (!window || check_window_valid(window, mode))
95
            break;
96
    }
97
 
98
+   if (is_uwp_window(window)) {
99
+       HWND child = get_uwp_actual_window(window);
100
+       if (child) {
101
+           *parent = window;
102
+           return child;
103
+       }
104
+   }
105
+
106
    return window;
107
 }
108
 
109
-static inline HWND first_window(enum window_search_mode mode)
110
+static inline HWND first_window(enum window_search_mode mode, HWND *parent)
111
 {
112
-   HWND window = GetWindow(GetDesktopWindow(), GW_CHILD);
113
+   HWND window = FindWindowEx(GetDesktopWindow(), NULL, NULL, NULL);
114
+
115
+   *parent = NULL;
116
+
117
    if (!check_window_valid(window, mode))
118
-       window = next_window(window, mode);
119
+       window = next_window(window, mode, parent);
120
+
121
+   if (is_uwp_window(window)) {
122
+       HWND child = get_uwp_actual_window(window);
123
+       if (child) {
124
+           *parent = window;
125
+           return child;
126
+       }
127
+   }
128
+
129
    return window;
130
 }
131
 
132
 void fill_window_list(obs_property_t *p, enum window_search_mode mode,
133
        add_window_cb callback)
134
 {
135
-   HWND window = first_window(mode);
136
+   HWND parent;
137
+   HWND window = first_window(mode, &parent);
138
 
139
    while (window) {
140
        add_window(p, window, callback);
141
-       window = next_window(window, mode);
142
+       window = next_window(window, mode, &parent);
143
    }
144
 }
145
 
146
@@ -226,7 +316,8 @@
147
        enum window_priority priority,
148
        const char *class,
149
        const char *title,
150
-       const char *exe)
151
+       const char *exe,
152
+       bool uwp_window)
153
 {
154
    struct dstr cur_class = {0};
155
    struct dstr cur_title = {0};
156
@@ -248,12 +339,18 @@
157
    else
158
        exe_val += 3;
159
 
160
-   if (dstr_cmpi(&cur_class, class) == 0)
161
-       total += class_val;
162
-   if (dstr_cmpi(&cur_title, title) == 0)
163
-       total += title_val;
164
-   if (dstr_cmpi(&cur_exe, exe) == 0)
165
-       total += exe_val;
166
+   if (uwp_window) {
167
+       if (dstr_cmpi(&cur_title, title) == 0 &&
168
+           dstr_cmpi(&cur_exe, exe) == 0)
169
+           total += exe_val + title_val + class_val;
170
+   } else {
171
+       if (dstr_cmpi(&cur_class, class) == 0)
172
+           total += class_val;
173
+       if (dstr_cmpi(&cur_title, title) == 0)
174
+           total += title_val;
175
+       if (dstr_cmpi(&cur_exe, exe) == 0)
176
+           total += exe_val;
177
+   }
178
 
179
    dstr_free(&cur_class);
180
    dstr_free(&cur_title);
181
@@ -268,18 +365,25 @@
182
        const char *title,
183
        const char *exe)
184
 {
185
-   HWND window      = first_window(mode);
186
+   HWND parent;
187
+   HWND window      = first_window(mode, &parent);
188
    HWND best_window = NULL;
189
    int  best_rating = 0;
190
 
191
+   if (!class)
192
+       return NULL;
193
+
194
+   bool uwp_window  = strcmp(class, "Windows.UI.Core.CoreWindow") == 0;
195
+
196
    while (window) {
197
-       int rating = window_rating(window, priority, class, title, exe);
198
+       int rating = window_rating(window, priority, class, title, exe,
199
+               uwp_window);
200
        if (rating > best_rating) {
201
            best_rating = rating;
202
            best_window = window;
203
        }
204
 
205
-       window = next_window(window, mode);
206
+       window = next_window(window, mode, &parent);
207
    }
208
 
209
    return best_window;
210
obs-studio-0.16.6.tar.xz/plugins/win-capture/window-helpers.h -> obs-studio-0.17.0.tar.xz/plugins/win-capture/window-helpers.h Changed
10
 
1
@@ -16,6 +16,8 @@
2
 extern bool get_window_exe(struct dstr *name, HWND window);
3
 extern void get_window_title(struct dstr *name, HWND hwnd);
4
 extern void get_window_class(struct dstr *class, HWND hwnd);
5
+extern bool is_uwp_window(HWND hwnd);
6
+extern HWND get_uwp_actual_window(HWND parent);
7
 
8
 typedef bool (*add_window_cb)(const char *title, const char *class,
9
        const char *exe);
10
obs-studio-0.16.6.tar.xz/plugins/win-dshow/data/locale/tr-TR.ini -> obs-studio-0.17.0.tar.xz/plugins/win-dshow/data/locale/tr-TR.ini Changed
11
 
1
@@ -24,6 +24,9 @@
2
 UseCustomAudioDevice="Özel ses aygıtını kullan"
3
 AudioDevice="Ses Aygıtı"
4
 Buffering="Arabelleğe Alma"
5
+Buffering.AutoDetect="Otomatik Algıla"
6
+Buffering.Enable="Etkinleştir"
7
+Buffering.Disable="Devre Dışı Bırak"
8
 Activate="Etkinleştir"
9
 Deactivate="Devredışı Bırak"
10
 FlipVertically="Dikey Çevir"
11
obs-studio-0.16.6.tar.xz/plugins/win-ivcam/seg_service/CMakeLists.txt -> obs-studio-0.17.0.tar.xz/plugins/win-ivcam/seg_service/CMakeLists.txt Changed
12
 
1
@@ -33,6 +33,10 @@
2
    ${seg_service_GENERATED_FILES}
3
    )
4
 
5
+if(MSVC)
6
+   add_compile_options("$<$<CONFIG:RelWithDebInfo>:/MT>")
7
+endif()
8
+
9
 add_executable(seg_service WIN32
10
    ${seg_service_SOURCES}
11
    ${seg_service_HEADERS})
12
obs-studio-0.16.6.tar.xz/plugins/win-mf/data/locale/tr-TR.ini -> obs-studio-0.17.0.tar.xz/plugins/win-mf/data/locale/tr-TR.ini Changed
11
 
1
@@ -8,6 +8,9 @@
2
 MF.H264.Bitrate="Bithızı"
3
 MF.H264.MaxBitrate="Maks Bit hızı"
4
 MF.H264.KeyframeIntervalSec="Anahtarkare Aralığı (saniye, 0=otomatik)"
5
+MF.H264.VBR="VBR (Değişken Bit Hızı)"
6
+MF.H264.MinQP="Minimum QP"
7
+MF.H264.MaxQP="Maksimum QP"
8
 MF.H264.Profile="Profil"
9
 MF.H264.Advanced="Gelişmiş"
10
 
11
obs-studio-0.16.6.tar.xz/plugins/win-wasapi/data/locale/nl-NL.ini -> obs-studio-0.17.0.tar.xz/plugins/win-wasapi/data/locale/nl-NL.ini Changed
7
 
1
@@ -1,4 +1,4 @@
2
-AudioInput="Audioinvoer Capture"
3
+AudioInput="Audioinvoer Opname"
4
 AudioOutput="Audiouitvoer Opname"
5
 Device="Apparaat"
6
 Default="Standaardinstellingen"
7
Refresh

No build results available

Refresh

No rpmlint results available

Request History
boombatower's avatar

boombatower created request over 8 years ago

- Update to version 0.17.0:
* rtmp-services: Update ingest list for Restream.io
* Revert "CI: Build on OSX 10.10 on travis"
* Remove python dep
* win-capture: Use static runtimes for hooks/helpers
* cmake: Fix OSX fixup_bundle.sh to copy non-system deps
* cmake: Fix permissions with OSX fixup_bundle.sh
* libobs-opengl: Add xcb message poll to empty out the queue
* frontend-tools: Add options to start output timers every time
* libobs-d3d11: Add optional macro to log shader disassembly
* Revert "obs-transitions: Avoid branching in slide_transition.effect"
* rtmp-services: remove shut down services
* libff: Allow custom demuxer options
* obs-outputs: Fix librtmp IP bind / resolve behavior
* UI: Fix frontend-api event call for adding scenes
* libobs/util: Add function to get circlebuf data offset
* libobs/util: Add function to generate formatted filenames
* libobs: Fix bug where outputs cannot initialize hotkeys
* cmake: Add _CRT_SECURE_NO_WARNINGS to all projects
* libobs: Fix deprecated macro
* libobs/util: Do not ignore deprecation on windows
* libobs: Use reference counting for encoder packets
* obs-ffmpeg: Add replay buffer output
* UI: Disable simple output rec. settings when active
* UI: Add replay buffer options to simple output mode
* UI: Clarify replay buf. hotkey error message
* UI: Separate replay buffer from recording
* UI: Add file prefix/suffix options for replay buffer
* UI: Fix replay buffer compile issues on older compilers
* win-capture: Only duplicate to get cur thread handle
* win-capture: Always use minimal access rights within hook
* win-capture: Do not require pipe/mutex within hook
* win-capture: Fix getting proper UWP window handles
* win-capture: Use window for keepalive check
* win-capture: Create all named objects within hook
* win-capture: Don't use "Local\" for game capture shared mem
* win-capture: Remove redundant function
* win-capture: Use wide strings for named objects
* win-capture: Add ability to open UWP named kernel objects
* win-capture: Open UWP named objects with helper functions
* win-capture: Output hook debug messages if addresses missing
* win-capture: Log plugin-side when capture successful/lost
* win-capture: Don't hook suspended processes
* win-capture: Wait a few frames for hook to load
* win-capture: Fix "attempting to hook [executable]" message
* win-capture: Add ApplicationFrameHost to game capture blacklist
* win-capture: Don't hard fail if thread ID not found
* win-capture: Fix cursor not painting with UWP windows
* win-capture: Add debug messages when hooking
* win-capture: Do not fall back to other windows for UWP windows
* UI: Fix property name bug in frontend API
* libobs: Fix possible reverse order mutex hard lock
* UI: Remove deleteLater view from filter window layout
* libobs: Convert Y800 to RGBX manually
* UI: Use dedicated GPU on Hybrid AMD GPU systems
* libobs: Fix format not being set for new source frames
* libobs: Fix line size issue when copying Y800 data
* obs-ffmpeg: Don't allow 32kb/s with FFmpeg AAC encoder
* libobs/graphics: Fix the 2D vector dot product func
* UI: Make close button default in transform dialog
* UI: Add ability to copy-paste scene item transforms
* UI: Add import/export of scene collections & profiles
* enc-amf: Update to 1.4.3.4 for AMD Driver 16.12.1
* obs-filters: Improve "Color Correction" filter
* image-source: Do not change blend state
* obs-text: Do not reset blend state
* libobs-d3d11: Don't crash if unable to rebuild shared texture
* libobs: Increase maximum audio tracks to 6
* UI: Increase maximum audio tracks to 6
* UI: Update locale for 6 tracks
* UI: Fix endif in installer
* UI: Use 64bit desktop link by default in installer
* UI: Clarify startup error messages related to video
* obs-ffmpeg: Fix nvenc_h264 deprecated message
* libobs: Fix bug drawing RGB/BGR async sources
* libobs: Process all scene audio actions if no audio playing
* UI: Fix buddy controls with new audio tracks
* UI: Add default audio track bitrates
* UI: Fix video initialization failure error message
* UI: Fix settings window stacked widget index
* win-capture: Capture all D3D12 backbuffers
* win-capture: Use FindWindowEx to traverse window list
* win-capture: Fix possible null pointer dereference
* win-capture: Do not add certain windows to window lists
* win-capture: Add a few new blacklisted game capture exes
* obs-filters: Add "Color" option to color correction filter
* obs-filters: Fix comment messages
* obs-qsv11: Use d3d9 allocator on Win7
* win-capture: Fix possible access of array beyond size
* win-capture: Refactor DX12 backbuffer code
* win-capture: If backbuffer count is 1, disable dxgi 1.4 use
* win-capture: Release backbuffers immediately upon init
* libobs/util: Fix C++ compilation issue
* Add libcaption library
* libobs: Add ability to insert captions into frames
* frontend-tools: Move source helper functions to a header
* frontend-tools: Add caption generation tool (windows)
* Update translations from Crowdin
* frontend-tools: Add ability to select caption language
* frontend-tools: Detach caption thread if critical failure
* frontend-tools: Reset stop event before starting captions
* frontend-tools: Don't include colon in "Audio Source"
* frontend-tools: Set buddied controls for captions dialog
* libobs: Fix caption encoder packet reallocation
* libobs: Create referenced parsed AVC encoder packet
* obs-outputs: Free encoder packet data manually
* libobs: Fix bug in AVC encoder packet allocation
* UI: Fix Export QFileDialog parent
* libobs: Eliminate an unnecessary allocation with captions
* frontend-tools: Fix output-timer translation bug
* libobs: Update to version 17.0.0


boombatower's avatar

boombatower accepted request over 8 years ago

ok