multitrack-video.hpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /*
  2. * Copyright (c) 2024 Ruwen Hahn <[email protected]>
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #pragma once
  17. #include <string>
  18. #include <optional>
  19. #include <unordered_set>
  20. #include <obs.h>
  21. #include <nlohmann/json.hpp>
  22. /*
  23. * Support for (de-)serialising std::optional
  24. * From https://github.com/nlohmann/json/issues/1749#issuecomment-1731266676
  25. * whatsnew.hpp's version doesn't seem to work here
  26. */
  27. template<typename T> struct nlohmann::adl_serializer<std::optional<T>> {
  28. static void from_json(const json &j, std::optional<T> &opt)
  29. {
  30. if (j.is_null()) {
  31. opt = std::nullopt;
  32. } else {
  33. opt = j.get<T>();
  34. }
  35. }
  36. static void to_json(json &json, std::optional<T> t)
  37. {
  38. if (t) {
  39. json = *t;
  40. } else {
  41. json = nullptr;
  42. }
  43. }
  44. };
  45. NLOHMANN_JSON_SERIALIZE_ENUM(obs_scale_type, {
  46. {OBS_SCALE_DISABLE, "OBS_SCALE_DISABLE"},
  47. {OBS_SCALE_POINT, "OBS_SCALE_POINT"},
  48. {OBS_SCALE_BICUBIC, "OBS_SCALE_BICUBIC"},
  49. {OBS_SCALE_BILINEAR, "OBS_SCALE_BILINEAR"},
  50. {OBS_SCALE_LANCZOS, "OBS_SCALE_LANCZOS"},
  51. {OBS_SCALE_AREA, "OBS_SCALE_AREA"},
  52. })
  53. NLOHMANN_JSON_SERIALIZE_ENUM(video_colorspace, {
  54. {VIDEO_CS_DEFAULT, "VIDEO_CS_DEFAULT"},
  55. {VIDEO_CS_601, "VIDEO_CS_601"},
  56. {VIDEO_CS_709, "VIDEO_CS_709"},
  57. {VIDEO_CS_SRGB, "VIDEO_CS_SRGB"},
  58. {VIDEO_CS_2100_PQ, "VIDEO_CS_2100_PQ"},
  59. {VIDEO_CS_2100_HLG, "VIDEO_CS_2100_HLG"},
  60. })
  61. /* This only includes output formats selectable in advanced settings. */
  62. NLOHMANN_JSON_SERIALIZE_ENUM(video_format, {
  63. {VIDEO_FORMAT_NONE, "VIDEO_FORMAT_NONE"},
  64. {VIDEO_FORMAT_I420, "VIDEO_FORMAT_I420"},
  65. {VIDEO_FORMAT_NV12, "VIDEO_FORMAT_NV12"},
  66. {VIDEO_FORMAT_BGRA, "VIDEO_FORMAT_BGRA"},
  67. {VIDEO_FORMAT_I444, "VIDEO_FORMAT_I444"},
  68. {VIDEO_FORMAT_I010, "VIDEO_FORMAT_I010"},
  69. {VIDEO_FORMAT_P010, "VIDEO_FORMAT_P010"},
  70. {VIDEO_FORMAT_P216, "VIDEO_FORMAT_P216"},
  71. {VIDEO_FORMAT_P416, "VIDEO_FORMAT_P416"},
  72. })
  73. NLOHMANN_JSON_SERIALIZE_ENUM(video_range_type, {
  74. {VIDEO_RANGE_DEFAULT, "VIDEO_RANGE_DEFAULT"},
  75. {VIDEO_RANGE_PARTIAL, "VIDEO_RANGE_PARTIAL"},
  76. {VIDEO_RANGE_FULL, "VIDEO_RANGE_FULL"},
  77. })
  78. NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(media_frames_per_second, numerator, denominator)
  79. namespace GoLiveApi {
  80. using std::string;
  81. using std::optional;
  82. using json = nlohmann::json;
  83. struct Client {
  84. string name = "obs-studio";
  85. string version;
  86. std::unordered_set<std::string> supported_codecs;
  87. NLOHMANN_DEFINE_TYPE_INTRUSIVE(Client, name, version, supported_codecs)
  88. };
  89. struct Cpu {
  90. int32_t physical_cores;
  91. int32_t logical_cores;
  92. optional<uint32_t> speed;
  93. optional<string> name;
  94. NLOHMANN_DEFINE_TYPE_INTRUSIVE(Cpu, physical_cores, logical_cores, speed, name)
  95. };
  96. struct Memory {
  97. uint64_t total;
  98. uint64_t free;
  99. NLOHMANN_DEFINE_TYPE_INTRUSIVE(Memory, total, free)
  100. };
  101. struct Gpu {
  102. string model;
  103. uint32_t vendor_id;
  104. uint32_t device_id;
  105. uint64_t dedicated_video_memory;
  106. uint64_t shared_system_memory;
  107. optional<string> driver_version;
  108. NLOHMANN_DEFINE_TYPE_INTRUSIVE(Gpu, model, vendor_id, device_id, dedicated_video_memory, shared_system_memory,
  109. driver_version)
  110. };
  111. struct GamingFeatures {
  112. optional<bool> game_bar_enabled;
  113. optional<bool> game_dvr_allowed;
  114. optional<bool> game_dvr_enabled;
  115. optional<bool> game_dvr_bg_recording;
  116. optional<bool> game_mode_enabled;
  117. optional<bool> hags_enabled;
  118. NLOHMANN_DEFINE_TYPE_INTRUSIVE(GamingFeatures, game_bar_enabled, game_dvr_allowed, game_dvr_enabled,
  119. game_dvr_bg_recording, game_mode_enabled, hags_enabled)
  120. };
  121. struct System {
  122. string version;
  123. string name;
  124. int build;
  125. string release;
  126. string revision;
  127. int bits;
  128. bool arm;
  129. bool armEmulation;
  130. NLOHMANN_DEFINE_TYPE_INTRUSIVE(System, version, name, build, release, revision, bits, arm, armEmulation)
  131. };
  132. struct Capabilities {
  133. Cpu cpu;
  134. Memory memory;
  135. optional<GamingFeatures> gaming_features;
  136. System system;
  137. optional<std::vector<Gpu>> gpu;
  138. NLOHMANN_DEFINE_TYPE_INTRUSIVE(Capabilities, cpu, memory, gaming_features, system, gpu)
  139. };
  140. struct Canvas {
  141. uint32_t width;
  142. uint32_t height;
  143. uint32_t canvas_width;
  144. uint32_t canvas_height;
  145. media_frames_per_second framerate;
  146. NLOHMANN_DEFINE_TYPE_INTRUSIVE(Canvas, width, height, canvas_width, canvas_height, framerate)
  147. };
  148. struct Preferences {
  149. optional<uint64_t> maximum_aggregate_bitrate;
  150. optional<uint32_t> maximum_video_tracks;
  151. bool vod_track_audio;
  152. optional<uint32_t> composition_gpu_index;
  153. uint32_t audio_samples_per_sec;
  154. uint32_t audio_channels;
  155. uint32_t audio_max_buffering_ms;
  156. bool audio_fixed_buffering;
  157. std::vector<Canvas> canvases;
  158. NLOHMANN_DEFINE_TYPE_INTRUSIVE(Preferences, maximum_aggregate_bitrate, maximum_video_tracks, vod_track_audio,
  159. composition_gpu_index, audio_samples_per_sec, audio_channels,
  160. audio_max_buffering_ms, audio_fixed_buffering, canvases)
  161. };
  162. struct PostData {
  163. string service;
  164. string schema_version;
  165. string authentication;
  166. Client client;
  167. Capabilities capabilities;
  168. Preferences preferences;
  169. NLOHMANN_DEFINE_TYPE_INTRUSIVE(PostData, service, schema_version, authentication, client, capabilities,
  170. preferences)
  171. };
  172. // Config Response
  173. struct Meta {
  174. string service;
  175. string schema_version;
  176. string config_id;
  177. NLOHMANN_DEFINE_TYPE_INTRUSIVE(Meta, service, schema_version, config_id)
  178. };
  179. enum struct StatusResult {
  180. Unknown,
  181. Success,
  182. Warning,
  183. Error,
  184. };
  185. NLOHMANN_JSON_SERIALIZE_ENUM(StatusResult, {
  186. {StatusResult::Unknown, nullptr},
  187. {StatusResult::Success, "success"},
  188. {StatusResult::Warning, "warning"},
  189. {StatusResult::Error, "error"},
  190. })
  191. struct Status {
  192. StatusResult result = StatusResult::Unknown;
  193. optional<string> html_en_us;
  194. NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Status, result, html_en_us)
  195. };
  196. struct IngestEndpoint {
  197. string protocol;
  198. string url_template;
  199. optional<string> authentication;
  200. NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(IngestEndpoint, protocol, url_template, authentication)
  201. };
  202. struct VideoEncoderConfiguration {
  203. string type;
  204. uint32_t width;
  205. uint32_t height;
  206. optional<media_frames_per_second> framerate;
  207. optional<obs_scale_type> gpu_scale_type;
  208. optional<video_colorspace> colorspace;
  209. optional<video_range_type> range;
  210. optional<video_format> format;
  211. json settings;
  212. uint32_t canvas_index;
  213. NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(VideoEncoderConfiguration, type, width, height, framerate,
  214. gpu_scale_type, colorspace, range, format, settings, canvas_index)
  215. };
  216. struct AudioEncoderConfiguration {
  217. string codec;
  218. uint32_t track_id;
  219. uint32_t channels;
  220. json settings;
  221. NLOHMANN_DEFINE_TYPE_INTRUSIVE(AudioEncoderConfiguration, codec, track_id, channels, settings)
  222. };
  223. struct AudioConfigurations {
  224. std::vector<AudioEncoderConfiguration> live;
  225. optional<std::vector<AudioEncoderConfiguration>> vod;
  226. NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(AudioConfigurations, live, vod)
  227. };
  228. struct Config {
  229. Meta meta;
  230. optional<Status> status;
  231. std::vector<IngestEndpoint> ingest_endpoints;
  232. std::vector<VideoEncoderConfiguration> encoder_configurations;
  233. AudioConfigurations audio_configurations;
  234. NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Config, meta, status, ingest_endpoints, encoder_configurations,
  235. audio_configurations)
  236. };
  237. } // namespace GoLiveApi