multitrack-video.hpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  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 <obs.h>
  20. #include <nlohmann/json.hpp>
  21. /* From whatsnew.hpp */
  22. #ifndef NLOHMANN_DEFINE_TYPE_INTRUSIVE
  23. #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
  24. friend void to_json(nlohmann::json &nlohmann_json_j, \
  25. const Type &nlohmann_json_t) \
  26. { \
  27. NLOHMANN_JSON_EXPAND( \
  28. NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \
  29. } \
  30. friend void from_json(const nlohmann::json &nlohmann_json_j, \
  31. Type &nlohmann_json_t) \
  32. { \
  33. NLOHMANN_JSON_EXPAND( \
  34. NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) \
  35. }
  36. #endif
  37. #ifndef NLOHMANN_JSON_FROM_WITH_DEFAULT
  38. #define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) \
  39. nlohmann_json_t.v1 = \
  40. nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
  41. #endif
  42. #ifndef NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT
  43. #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
  44. friend void to_json(nlohmann::json &nlohmann_json_j, \
  45. const Type &nlohmann_json_t) \
  46. { \
  47. NLOHMANN_JSON_EXPAND( \
  48. NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \
  49. } \
  50. friend void from_json(const nlohmann::json &nlohmann_json_j, \
  51. Type &nlohmann_json_t) \
  52. { \
  53. Type nlohmann_json_default_obj; \
  54. NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE( \
  55. NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) \
  56. }
  57. #endif
  58. /*
  59. * Support for (de-)serialising std::optional
  60. * From https://github.com/nlohmann/json/issues/1749#issuecomment-1731266676
  61. * whatsnew.hpp's version doesn't seem to work here
  62. */
  63. template<typename T> struct nlohmann::adl_serializer<std::optional<T>> {
  64. static void from_json(const json &j, std::optional<T> &opt)
  65. {
  66. if (j.is_null()) {
  67. opt = std::nullopt;
  68. } else {
  69. opt = j.get<T>();
  70. }
  71. }
  72. static void to_json(json &json, std::optional<T> t)
  73. {
  74. if (t) {
  75. json = *t;
  76. } else {
  77. json = nullptr;
  78. }
  79. }
  80. };
  81. NLOHMANN_JSON_SERIALIZE_ENUM(obs_scale_type,
  82. {
  83. {OBS_SCALE_DISABLE, "OBS_SCALE_DISABLE"},
  84. {OBS_SCALE_POINT, "OBS_SCALE_POINT"},
  85. {OBS_SCALE_BICUBIC, "OBS_SCALE_BICUBIC"},
  86. {OBS_SCALE_BILINEAR, "OBS_SCALE_BILINEAR"},
  87. {OBS_SCALE_LANCZOS, "OBS_SCALE_LANCZOS"},
  88. {OBS_SCALE_AREA, "OBS_SCALE_AREA"},
  89. })
  90. NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(media_frames_per_second, numerator,
  91. denominator)
  92. namespace GoLiveApi {
  93. using std::string;
  94. using std::optional;
  95. using json = nlohmann::json;
  96. struct Client {
  97. string name = "obs-studio";
  98. string version;
  99. bool vod_track_audio;
  100. uint32_t width;
  101. uint32_t height;
  102. uint32_t fps_numerator;
  103. uint32_t fps_denominator;
  104. uint32_t canvas_width;
  105. uint32_t canvas_height;
  106. NLOHMANN_DEFINE_TYPE_INTRUSIVE(Client, name, version, vod_track_audio,
  107. width, height, fps_numerator,
  108. fps_denominator, canvas_width,
  109. canvas_height)
  110. };
  111. struct Cpu {
  112. int32_t physical_cores;
  113. int32_t logical_cores;
  114. optional<uint32_t> speed;
  115. optional<string> name;
  116. NLOHMANN_DEFINE_TYPE_INTRUSIVE(Cpu, physical_cores, logical_cores,
  117. speed, name)
  118. };
  119. struct Memory {
  120. uint64_t total;
  121. uint64_t free;
  122. NLOHMANN_DEFINE_TYPE_INTRUSIVE(Memory, total, free)
  123. };
  124. struct Gpu {
  125. string model;
  126. uint32_t vendor_id;
  127. uint32_t device_id;
  128. uint64_t dedicated_video_memory;
  129. uint64_t shared_system_memory;
  130. string luid;
  131. optional<string> driver_version;
  132. NLOHMANN_DEFINE_TYPE_INTRUSIVE(Gpu, model, vendor_id, device_id,
  133. dedicated_video_memory,
  134. shared_system_memory, luid,
  135. driver_version)
  136. };
  137. struct GamingFeatures {
  138. optional<bool> game_bar_enabled;
  139. optional<bool> game_dvr_allowed;
  140. optional<bool> game_dvr_enabled;
  141. optional<bool> game_dvr_bg_recording;
  142. optional<bool> game_mode_enabled;
  143. optional<bool> hags_enabled;
  144. NLOHMANN_DEFINE_TYPE_INTRUSIVE(GamingFeatures, game_bar_enabled,
  145. game_dvr_allowed, game_dvr_enabled,
  146. game_dvr_bg_recording, game_mode_enabled,
  147. hags_enabled)
  148. };
  149. struct System {
  150. string version;
  151. string name;
  152. int build;
  153. string release;
  154. int revision;
  155. int bits;
  156. bool arm;
  157. bool armEmulation;
  158. NLOHMANN_DEFINE_TYPE_INTRUSIVE(System, version, name, build, release,
  159. revision, bits, arm, armEmulation)
  160. };
  161. struct Capabilities {
  162. Client client;
  163. Cpu cpu;
  164. Memory memory;
  165. optional<GamingFeatures> gaming_features;
  166. System system;
  167. optional<std::vector<Gpu>> gpu;
  168. NLOHMANN_DEFINE_TYPE_INTRUSIVE(Capabilities, client, cpu, memory,
  169. gaming_features, system, gpu)
  170. };
  171. struct Preferences {
  172. optional<uint64_t> maximum_aggregate_bitrate;
  173. optional<uint32_t> maximum_video_tracks;
  174. NLOHMANN_DEFINE_TYPE_INTRUSIVE(Preferences, maximum_aggregate_bitrate,
  175. maximum_video_tracks)
  176. };
  177. struct PostData {
  178. string service = "IVS";
  179. string schema_version = "2023-05-10";
  180. string authentication;
  181. Capabilities capabilities;
  182. Preferences preferences;
  183. NLOHMANN_DEFINE_TYPE_INTRUSIVE(PostData, service, schema_version,
  184. authentication, capabilities,
  185. preferences)
  186. };
  187. // Config Response
  188. struct Meta {
  189. string service;
  190. string schema_version;
  191. string config_id;
  192. NLOHMANN_DEFINE_TYPE_INTRUSIVE(Meta, service, schema_version, config_id)
  193. };
  194. enum struct StatusResult {
  195. Unknown,
  196. Success,
  197. Warning,
  198. Error,
  199. };
  200. NLOHMANN_JSON_SERIALIZE_ENUM(StatusResult,
  201. {
  202. {StatusResult::Unknown, nullptr},
  203. {StatusResult::Success, "success"},
  204. {StatusResult::Warning, "warning"},
  205. {StatusResult::Error, "error"},
  206. })
  207. struct Status {
  208. StatusResult result = StatusResult::Unknown;
  209. optional<string> html_en_us;
  210. NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Status, result, html_en_us)
  211. };
  212. struct IngestEndpoint {
  213. string protocol;
  214. string url_template;
  215. optional<string> authentication;
  216. NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(IngestEndpoint, protocol,
  217. url_template,
  218. authentication)
  219. };
  220. struct VideoEncoderConfiguration {
  221. string type;
  222. uint32_t width;
  223. uint32_t height;
  224. uint32_t bitrate;
  225. optional<media_frames_per_second> framerate;
  226. optional<obs_scale_type> gpu_scale_type;
  227. NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(VideoEncoderConfiguration,
  228. type, width, height,
  229. bitrate, framerate,
  230. gpu_scale_type)
  231. };
  232. struct AudioEncoderConfiguration {
  233. string codec;
  234. uint32_t track_id;
  235. uint32_t channels;
  236. uint32_t bitrate;
  237. NLOHMANN_DEFINE_TYPE_INTRUSIVE(AudioEncoderConfiguration, codec,
  238. track_id, channels, bitrate)
  239. };
  240. template<typename T> struct EncoderConfiguration {
  241. T config;
  242. json data;
  243. friend void to_json(nlohmann::json &nlohmann_json_j,
  244. const EncoderConfiguration<T> &nlohmann_json_t)
  245. {
  246. nlohmann_json_j = nlohmann_json_t.data;
  247. to_json(nlohmann_json_j, nlohmann_json_t.config);
  248. }
  249. friend void from_json(const nlohmann::json &nlohmann_json_j,
  250. EncoderConfiguration<T> &nlohmann_json_t)
  251. {
  252. nlohmann_json_t.data = nlohmann_json_j;
  253. nlohmann_json_j.get_to(nlohmann_json_t.config);
  254. }
  255. };
  256. struct AudioConfigurations {
  257. std::vector<EncoderConfiguration<AudioEncoderConfiguration>> live;
  258. std::vector<EncoderConfiguration<AudioEncoderConfiguration>> vod;
  259. NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(AudioConfigurations, live,
  260. vod)
  261. };
  262. struct Config {
  263. Meta meta;
  264. optional<Status> status;
  265. std::vector<IngestEndpoint> ingest_endpoints;
  266. std::vector<EncoderConfiguration<VideoEncoderConfiguration>>
  267. encoder_configurations;
  268. AudioConfigurations audio_configurations;
  269. NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Config, meta, status,
  270. ingest_endpoints,
  271. encoder_configurations,
  272. audio_configurations)
  273. };
  274. } // namespace GoLiveApi