obs-output.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363
  1. /******************************************************************************
  2. Copyright (C) 2013-2014 by Hugh Bailey <[email protected]>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ******************************************************************************/
  14. #include <inttypes.h>
  15. #include "util/platform.h"
  16. #include "obs.h"
  17. #include "obs-internal.h"
  18. static inline void signal_stop(struct obs_output *output, int code);
  19. const struct obs_output_info *find_output(const char *id)
  20. {
  21. size_t i;
  22. for (i = 0; i < obs->output_types.num; i++)
  23. if (strcmp(obs->output_types.array[i].id, id) == 0)
  24. return obs->output_types.array+i;
  25. return NULL;
  26. }
  27. const char *obs_output_get_display_name(const char *id)
  28. {
  29. const struct obs_output_info *info = find_output(id);
  30. return (info != NULL) ? info->get_name() : NULL;
  31. }
  32. static const char *output_signals[] = {
  33. "void start(ptr output)",
  34. "void stop(ptr output, int code)",
  35. "void reconnect(ptr output)",
  36. "void reconnect_success(ptr output)",
  37. NULL
  38. };
  39. static bool init_output_handlers(struct obs_output *output, const char *name,
  40. obs_data_t *settings, obs_data_t *hotkey_data)
  41. {
  42. if (!obs_context_data_init(&output->context, settings, name,
  43. hotkey_data))
  44. return false;
  45. signal_handler_add_array(output->context.signals, output_signals);
  46. return true;
  47. }
  48. obs_output_t *obs_output_create(const char *id, const char *name,
  49. obs_data_t *settings, obs_data_t *hotkey_data)
  50. {
  51. const struct obs_output_info *info = find_output(id);
  52. struct obs_output *output;
  53. int ret;
  54. if (!info) {
  55. blog(LOG_ERROR, "Output '%s' not found", id);
  56. return NULL;
  57. }
  58. output = bzalloc(sizeof(struct obs_output));
  59. pthread_mutex_init_value(&output->interleaved_mutex);
  60. if (pthread_mutex_init(&output->interleaved_mutex, NULL) != 0)
  61. goto fail;
  62. if (!init_output_handlers(output, name, settings, hotkey_data))
  63. goto fail;
  64. output->info = *info;
  65. output->video = obs_get_video();
  66. output->audio = obs_get_audio();
  67. if (output->info.get_defaults)
  68. output->info.get_defaults(output->context.settings);
  69. ret = os_event_init(&output->reconnect_stop_event,
  70. OS_EVENT_TYPE_MANUAL);
  71. if (ret < 0)
  72. goto fail;
  73. output->context.data = info->create(output->context.settings, output);
  74. if (!output->context.data)
  75. goto fail;
  76. output->reconnect_retry_sec = 2;
  77. output->reconnect_retry_max = 20;
  78. output->valid = true;
  79. output->control = bzalloc(sizeof(obs_weak_output_t));
  80. output->control->output = output;
  81. obs_context_data_insert(&output->context,
  82. &obs->data.outputs_mutex,
  83. &obs->data.first_output);
  84. blog(LOG_INFO, "output '%s' (%s) created", name, id);
  85. return output;
  86. fail:
  87. obs_output_destroy(output);
  88. return NULL;
  89. }
  90. static inline void free_packets(struct obs_output *output)
  91. {
  92. for (size_t i = 0; i < output->interleaved_packets.num; i++)
  93. obs_free_encoder_packet(output->interleaved_packets.array+i);
  94. da_free(output->interleaved_packets);
  95. }
  96. void obs_output_destroy(obs_output_t *output)
  97. {
  98. if (output) {
  99. obs_context_data_remove(&output->context);
  100. blog(LOG_INFO, "output '%s' destroyed", output->context.name);
  101. if (output->valid && output->active)
  102. obs_output_stop(output);
  103. if (output->service)
  104. output->service->output = NULL;
  105. free_packets(output);
  106. if (output->context.data)
  107. output->info.destroy(output->context.data);
  108. if (output->video_encoder) {
  109. obs_encoder_remove_output(output->video_encoder,
  110. output);
  111. }
  112. for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
  113. if (output->audio_encoders[i]) {
  114. obs_encoder_remove_output(
  115. output->audio_encoders[i],
  116. output);
  117. }
  118. }
  119. pthread_mutex_destroy(&output->interleaved_mutex);
  120. os_event_destroy(output->reconnect_stop_event);
  121. obs_context_data_free(&output->context);
  122. bfree(output);
  123. }
  124. }
  125. const char *obs_output_get_name(const obs_output_t *output)
  126. {
  127. return output ? output->context.name : NULL;
  128. }
  129. bool obs_output_start(obs_output_t *output)
  130. {
  131. bool success;
  132. if (!output)
  133. return false;
  134. output->stopped = false;
  135. success = output->info.start(output->context.data);
  136. if (success && output->video) {
  137. output->starting_frame_count =
  138. video_output_get_total_frames(output->video);
  139. output->starting_skipped_frame_count =
  140. video_output_get_skipped_frames(output->video);
  141. }
  142. return success;
  143. }
  144. static void log_frame_info(struct obs_output *output)
  145. {
  146. uint32_t video_frames = video_output_get_total_frames(output->video);
  147. uint32_t video_skipped = video_output_get_skipped_frames(output->video);
  148. uint32_t total = video_frames - output->starting_frame_count;
  149. uint32_t skipped = video_skipped - output->starting_skipped_frame_count;
  150. int dropped = obs_output_get_frames_dropped(output);
  151. double percentage_skipped = (double)skipped / (double)total * 100.0;
  152. blog(LOG_INFO, "Output '%s': stopping", output->context.name);
  153. blog(LOG_INFO, "Output '%s': Total frames: %"PRIu32,
  154. output->context.name, total);
  155. if (total)
  156. blog(LOG_INFO, "Output '%s': Number of skipped frames: "
  157. "%"PRIu32" (%g%%)",
  158. output->context.name,
  159. skipped, percentage_skipped);
  160. if (dropped) {
  161. double percentage_dropped;
  162. percentage_dropped = (double)dropped / (double)total * 100.0;
  163. blog(LOG_INFO, "Output '%s': Number of dropped frames: "
  164. "%d (%g%%)",
  165. output->context.name,
  166. dropped, percentage_dropped);
  167. }
  168. }
  169. void obs_output_stop(obs_output_t *output)
  170. {
  171. if (output) {
  172. output->stopped = true;
  173. os_event_signal(output->reconnect_stop_event);
  174. if (output->reconnect_thread_active)
  175. pthread_join(output->reconnect_thread, NULL);
  176. output->info.stop(output->context.data);
  177. signal_stop(output, OBS_OUTPUT_SUCCESS);
  178. if (output->video)
  179. log_frame_info(output);
  180. }
  181. }
  182. bool obs_output_active(const obs_output_t *output)
  183. {
  184. return (output != NULL) ?
  185. (output->active || output->reconnecting) : false;
  186. }
  187. static inline obs_data_t *get_defaults(const struct obs_output_info *info)
  188. {
  189. obs_data_t *settings = obs_data_create();
  190. if (info->get_defaults)
  191. info->get_defaults(settings);
  192. return settings;
  193. }
  194. obs_data_t *obs_output_defaults(const char *id)
  195. {
  196. const struct obs_output_info *info = find_output(id);
  197. return (info) ? get_defaults(info) : NULL;
  198. }
  199. obs_properties_t *obs_get_output_properties(const char *id)
  200. {
  201. const struct obs_output_info *info = find_output(id);
  202. if (info && info->get_properties) {
  203. obs_data_t *defaults = get_defaults(info);
  204. obs_properties_t *properties;
  205. properties = info->get_properties(NULL);
  206. obs_properties_apply_settings(properties, defaults);
  207. obs_data_release(defaults);
  208. return properties;
  209. }
  210. return NULL;
  211. }
  212. obs_properties_t *obs_output_properties(const obs_output_t *output)
  213. {
  214. if (output && output->info.get_properties) {
  215. obs_properties_t *props;
  216. props = output->info.get_properties(output->context.data);
  217. obs_properties_apply_settings(props, output->context.settings);
  218. return props;
  219. }
  220. return NULL;
  221. }
  222. void obs_output_update(obs_output_t *output, obs_data_t *settings)
  223. {
  224. if (!output) return;
  225. obs_data_apply(output->context.settings, settings);
  226. if (output->info.update)
  227. output->info.update(output->context.data,
  228. output->context.settings);
  229. }
  230. obs_data_t *obs_output_get_settings(const obs_output_t *output)
  231. {
  232. if (!output)
  233. return NULL;
  234. obs_data_addref(output->context.settings);
  235. return output->context.settings;
  236. }
  237. bool obs_output_canpause(const obs_output_t *output)
  238. {
  239. return output ? (output->info.pause != NULL) : false;
  240. }
  241. void obs_output_pause(obs_output_t *output)
  242. {
  243. if (output && output->info.pause)
  244. output->info.pause(output->context.data);
  245. }
  246. signal_handler_t *obs_output_get_signal_handler(const obs_output_t *output)
  247. {
  248. return output ? output->context.signals : NULL;
  249. }
  250. proc_handler_t *obs_output_get_proc_handler(const obs_output_t *output)
  251. {
  252. return output ? output->context.procs : NULL;
  253. }
  254. void obs_output_set_media(obs_output_t *output, video_t *video, audio_t *audio)
  255. {
  256. if (!output)
  257. return;
  258. output->video = video;
  259. output->audio = audio;
  260. }
  261. video_t *obs_output_video(const obs_output_t *output)
  262. {
  263. return output ? output->video : NULL;
  264. }
  265. audio_t *obs_output_audio(const obs_output_t *output)
  266. {
  267. return output ? output->audio : NULL;
  268. }
  269. void obs_output_set_mixer(obs_output_t *output, size_t mixer_idx)
  270. {
  271. if (!output)
  272. return;
  273. if (!output->active)
  274. output->mixer_idx = mixer_idx;
  275. }
  276. size_t obs_output_get_mixer(const obs_output_t *output)
  277. {
  278. return output ? output->mixer_idx : 0;
  279. }
  280. void obs_output_remove_encoder(struct obs_output *output,
  281. struct obs_encoder *encoder)
  282. {
  283. if (!output) return;
  284. if (output->video_encoder == encoder) {
  285. output->video_encoder = NULL;
  286. } else {
  287. for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
  288. if (output->audio_encoders[i] == encoder)
  289. output->audio_encoders[i] = NULL;
  290. }
  291. }
  292. }
  293. void obs_output_set_video_encoder(obs_output_t *output, obs_encoder_t *encoder)
  294. {
  295. if (!output) return;
  296. if (output->video_encoder == encoder) return;
  297. if (encoder && encoder->info.type != OBS_ENCODER_VIDEO) return;
  298. obs_encoder_remove_output(output->video_encoder, output);
  299. obs_encoder_add_output(encoder, output);
  300. output->video_encoder = encoder;
  301. /* set the preferred resolution on the encoder */
  302. if (output->scaled_width && output->scaled_height)
  303. obs_encoder_set_scaled_size(output->video_encoder,
  304. output->scaled_width, output->scaled_height);
  305. }
  306. void obs_output_set_audio_encoder(obs_output_t *output, obs_encoder_t *encoder,
  307. size_t idx)
  308. {
  309. if (!output) return;
  310. if (encoder && encoder->info.type != OBS_ENCODER_AUDIO) return;
  311. if ((output->info.flags & OBS_OUTPUT_MULTI_TRACK) != 0) {
  312. if (idx >= MAX_AUDIO_MIXES) {
  313. return;
  314. }
  315. } else {
  316. if (idx > 0) {
  317. return;
  318. }
  319. }
  320. if (output->audio_encoders[idx] == encoder) return;
  321. obs_encoder_remove_output(output->audio_encoders[idx], output);
  322. obs_encoder_add_output(encoder, output);
  323. output->audio_encoders[idx] = encoder;
  324. }
  325. obs_encoder_t *obs_output_get_video_encoder(const obs_output_t *output)
  326. {
  327. return output ? output->video_encoder : NULL;
  328. }
  329. obs_encoder_t *obs_output_get_audio_encoder(const obs_output_t *output,
  330. size_t idx)
  331. {
  332. if (!output) return NULL;
  333. if ((output->info.flags & OBS_OUTPUT_MULTI_TRACK) != 0) {
  334. if (idx >= MAX_AUDIO_MIXES) {
  335. return NULL;
  336. }
  337. } else {
  338. if (idx > 0) {
  339. return NULL;
  340. }
  341. }
  342. return output->audio_encoders[idx];
  343. }
  344. void obs_output_set_service(obs_output_t *output, obs_service_t *service)
  345. {
  346. if (!output || output->active || !service || service->active) return;
  347. if (service->output)
  348. service->output->service = NULL;
  349. output->service = service;
  350. service->output = output;
  351. }
  352. obs_service_t *obs_output_get_service(const obs_output_t *output)
  353. {
  354. return output ? output->service : NULL;
  355. }
  356. void obs_output_set_reconnect_settings(obs_output_t *output,
  357. int retry_count, int retry_sec)
  358. {
  359. if (!output) return;
  360. output->reconnect_retry_max = retry_count;
  361. output->reconnect_retry_sec = retry_sec;
  362. }
  363. uint64_t obs_output_get_total_bytes(const obs_output_t *output)
  364. {
  365. if (!output || !output->info.get_total_bytes)
  366. return 0;
  367. return output->info.get_total_bytes(output->context.data);
  368. }
  369. int obs_output_get_frames_dropped(const obs_output_t *output)
  370. {
  371. if (!output || !output->info.get_dropped_frames)
  372. return 0;
  373. return output->info.get_dropped_frames(output->context.data);
  374. }
  375. int obs_output_get_total_frames(const obs_output_t *output)
  376. {
  377. return output ? output->total_frames : 0;
  378. }
  379. void obs_output_set_preferred_size(obs_output_t *output, uint32_t width,
  380. uint32_t height)
  381. {
  382. if (!output || (output->info.flags & OBS_OUTPUT_VIDEO) == 0)
  383. return;
  384. if (output->active) {
  385. blog(LOG_WARNING, "output '%s': Cannot set the preferred "
  386. "resolution while the output is active",
  387. obs_output_get_name(output));
  388. return;
  389. }
  390. output->scaled_width = width;
  391. output->scaled_height = height;
  392. if (output->info.flags & OBS_OUTPUT_ENCODED) {
  393. if (output->video_encoder)
  394. obs_encoder_set_scaled_size(output->video_encoder,
  395. width, height);
  396. }
  397. }
  398. uint32_t obs_output_get_width(const obs_output_t *output)
  399. {
  400. if (!output || (output->info.flags & OBS_OUTPUT_VIDEO) == 0)
  401. return 0;
  402. if (output->info.flags & OBS_OUTPUT_ENCODED)
  403. return obs_encoder_get_width(output->video_encoder);
  404. else
  405. return output->scaled_width != 0 ?
  406. output->scaled_width :
  407. video_output_get_width(output->video);
  408. }
  409. uint32_t obs_output_get_height(const obs_output_t *output)
  410. {
  411. if (!output || (output->info.flags & OBS_OUTPUT_VIDEO) == 0)
  412. return 0;
  413. if (output->info.flags & OBS_OUTPUT_ENCODED)
  414. return obs_encoder_get_height(output->video_encoder);
  415. else
  416. return output->scaled_height != 0 ?
  417. output->scaled_height :
  418. video_output_get_height(output->video);
  419. }
  420. void obs_output_set_video_conversion(obs_output_t *output,
  421. const struct video_scale_info *conversion)
  422. {
  423. if (!output || !conversion) return;
  424. output->video_conversion = *conversion;
  425. output->video_conversion_set = true;
  426. }
  427. void obs_output_set_audio_conversion(obs_output_t *output,
  428. const struct audio_convert_info *conversion)
  429. {
  430. if (!output || !conversion) return;
  431. output->audio_conversion = *conversion;
  432. output->audio_conversion_set = true;
  433. }
  434. static inline bool service_supports_multitrack(const struct obs_output *output)
  435. {
  436. const struct obs_service *service = output->service;
  437. if (!service || !service->info.supports_multitrack) {
  438. return false;
  439. }
  440. return service->info.supports_multitrack(service->context.data);
  441. }
  442. static inline size_t num_audio_mixes(const struct obs_output *output)
  443. {
  444. size_t mix_count = 1;
  445. if ((output->info.flags & OBS_OUTPUT_SERVICE) != 0) {
  446. if (!service_supports_multitrack(output)) {
  447. return 1;
  448. }
  449. }
  450. if ((output->info.flags & OBS_OUTPUT_MULTI_TRACK) != 0) {
  451. mix_count = 0;
  452. for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
  453. if (!output->audio_encoders[i])
  454. break;
  455. mix_count++;
  456. }
  457. }
  458. return mix_count;
  459. }
  460. static inline bool audio_valid(const struct obs_output *output, bool encoded)
  461. {
  462. if (encoded) {
  463. size_t mix_count = num_audio_mixes(output);
  464. if (!mix_count)
  465. return false;
  466. for (size_t i = 0; i < mix_count; i++) {
  467. if (!output->audio_encoders[i]) {
  468. return false;
  469. }
  470. }
  471. } else {
  472. if (!output->audio)
  473. return false;
  474. }
  475. return true;
  476. }
  477. static bool can_begin_data_capture(const struct obs_output *output,
  478. bool encoded, bool has_video, bool has_audio, bool has_service)
  479. {
  480. if (has_video) {
  481. if (encoded) {
  482. if (!output->video_encoder)
  483. return false;
  484. } else {
  485. if (!output->video)
  486. return false;
  487. }
  488. }
  489. if (has_audio) {
  490. if (!audio_valid(output, encoded)) {
  491. return false;
  492. }
  493. }
  494. if (has_service && !output->service)
  495. return false;
  496. return true;
  497. }
  498. static inline bool has_scaling(const struct obs_output *output)
  499. {
  500. uint32_t video_width = video_output_get_width(output->video);
  501. uint32_t video_height = video_output_get_height(output->video);
  502. return output->scaled_width && output->scaled_height &&
  503. (video_width != output->scaled_width ||
  504. video_height != output->scaled_height);
  505. }
  506. static inline struct video_scale_info *get_video_conversion(
  507. struct obs_output *output)
  508. {
  509. if (output->video_conversion_set) {
  510. if (!output->video_conversion.width)
  511. output->video_conversion.width =
  512. obs_output_get_width(output);
  513. if (!output->video_conversion.height)
  514. output->video_conversion.height =
  515. obs_output_get_height(output);
  516. return &output->video_conversion;
  517. } else if (has_scaling(output)) {
  518. const struct video_output_info *info =
  519. video_output_get_info(output->video);
  520. output->video_conversion.format = info->format;
  521. output->video_conversion.colorspace = VIDEO_CS_DEFAULT;
  522. output->video_conversion.range = VIDEO_RANGE_DEFAULT;
  523. output->video_conversion.width = output->scaled_width;
  524. output->video_conversion.height = output->scaled_height;
  525. return &output->video_conversion;
  526. }
  527. return NULL;
  528. }
  529. static inline struct audio_convert_info *get_audio_conversion(
  530. struct obs_output *output)
  531. {
  532. return output->audio_conversion_set ? &output->audio_conversion : NULL;
  533. }
  534. static size_t get_track_index(const struct obs_output *output,
  535. struct encoder_packet *pkt)
  536. {
  537. for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
  538. struct obs_encoder *encoder = output->audio_encoders[i];
  539. if (pkt->encoder == encoder)
  540. return i;
  541. }
  542. assert(false);
  543. return 0;
  544. }
  545. static inline void check_received(struct obs_output *output,
  546. struct encoder_packet *out)
  547. {
  548. if (out->type == OBS_ENCODER_VIDEO) {
  549. if (!output->received_video)
  550. output->received_video = true;
  551. } else {
  552. if (!output->received_audio)
  553. output->received_audio = true;
  554. }
  555. }
  556. static inline void apply_interleaved_packet_offset(struct obs_output *output,
  557. struct encoder_packet *out)
  558. {
  559. int64_t offset;
  560. /* audio and video need to start at timestamp 0, and the encoders
  561. * may not currently be at 0 when we get data. so, we store the
  562. * current dts as offset and subtract that value from the dts/pts
  563. * of the output packet. */
  564. offset = (out->type == OBS_ENCODER_VIDEO) ?
  565. output->video_offset : output->audio_offsets[out->track_idx];
  566. out->dts -= offset;
  567. out->pts -= offset;
  568. /* convert the newly adjusted dts to relative dts time to ensure proper
  569. * interleaving. if we're using an audio encoder that's already been
  570. * started on another output, then the first audio packet may not be
  571. * quite perfectly synced up in terms of system time (and there's
  572. * nothing we can really do about that), but it will always at least be
  573. * within a 23ish millisecond threshold (at least for AAC) */
  574. out->dts_usec = packet_dts_usec(out);
  575. }
  576. static inline bool has_higher_opposing_ts(struct obs_output *output,
  577. struct encoder_packet *packet)
  578. {
  579. if (packet->type == OBS_ENCODER_VIDEO)
  580. return output->highest_audio_ts > packet->dts_usec;
  581. else
  582. return output->highest_video_ts > packet->dts_usec;
  583. }
  584. static inline void send_interleaved(struct obs_output *output)
  585. {
  586. struct encoder_packet out = output->interleaved_packets.array[0];
  587. /* do not send an interleaved packet if there's no packet of the
  588. * opposing type of a higher timstamp in the interleave buffer.
  589. * this ensures that the timestamps are monotonic */
  590. if (!has_higher_opposing_ts(output, &out))
  591. return;
  592. if (out.type == OBS_ENCODER_VIDEO)
  593. output->total_frames++;
  594. da_erase(output->interleaved_packets, 0);
  595. if (!output->stopped)
  596. output->info.encoded_packet(output->context.data, &out);
  597. obs_free_encoder_packet(&out);
  598. }
  599. static inline void set_higher_ts(struct obs_output *output,
  600. struct encoder_packet *packet)
  601. {
  602. if (packet->type == OBS_ENCODER_VIDEO) {
  603. if (output->highest_video_ts < packet->dts_usec)
  604. output->highest_video_ts = packet->dts_usec;
  605. } else {
  606. if (output->highest_audio_ts < packet->dts_usec)
  607. output->highest_audio_ts = packet->dts_usec;
  608. }
  609. }
  610. static bool can_prune_interleaved_packet(struct obs_output *output, size_t idx)
  611. {
  612. struct encoder_packet *packet;
  613. struct encoder_packet *next;
  614. if (idx >= (output->interleaved_packets.num - 1))
  615. return false;
  616. packet = &output->interleaved_packets.array[idx];
  617. /* audio packets will almost always come before video packets,
  618. * so it should only ever be necessary to prune audio packets */
  619. if (packet->type != OBS_ENCODER_AUDIO)
  620. return false;
  621. next = &output->interleaved_packets.array[idx + 1];
  622. if (next->type == OBS_ENCODER_VIDEO &&
  623. next->dts_usec == packet->dts_usec)
  624. return false;
  625. return true;
  626. }
  627. static void prune_interleaved_packets(struct obs_output *output)
  628. {
  629. size_t start_idx = 0;
  630. while (can_prune_interleaved_packet(output, start_idx))
  631. start_idx++;
  632. if (start_idx) {
  633. for (size_t i = 0; i < start_idx; i++) {
  634. struct encoder_packet *packet =
  635. &output->interleaved_packets.array[i];
  636. obs_free_encoder_packet(packet);
  637. }
  638. da_erase_range(output->interleaved_packets, 0, start_idx);
  639. }
  640. }
  641. static struct encoder_packet *find_first_packet_type(struct obs_output *output,
  642. enum obs_encoder_type type, size_t audio_idx)
  643. {
  644. for (size_t i = 0; i < output->interleaved_packets.num; i++) {
  645. struct encoder_packet *packet =
  646. &output->interleaved_packets.array[i];
  647. if (packet->type == type) {
  648. if (type == OBS_ENCODER_AUDIO &&
  649. packet->track_idx != audio_idx) {
  650. continue;
  651. }
  652. return packet;
  653. }
  654. }
  655. return NULL;
  656. }
  657. static bool initialize_interleaved_packets(struct obs_output *output)
  658. {
  659. struct encoder_packet *video;
  660. struct encoder_packet *audio[MAX_AUDIO_MIXES];
  661. size_t audio_mixes = num_audio_mixes(output);
  662. video = find_first_packet_type(output, OBS_ENCODER_VIDEO, 0);
  663. if (!video)
  664. output->received_video = false;
  665. for (size_t i = 0; i < audio_mixes; i++) {
  666. audio[i] = find_first_packet_type(output, OBS_ENCODER_AUDIO, i);
  667. if (!audio[i]) {
  668. output->received_audio = false;
  669. return false;
  670. }
  671. }
  672. if (!video) {
  673. return false;
  674. }
  675. /* get new offsets */
  676. output->video_offset = video->dts;
  677. for (size_t i = 0; i < audio_mixes; i++)
  678. output->audio_offsets[i] = audio[i]->dts;
  679. /* subtract offsets from highest TS offset variables */
  680. output->highest_audio_ts -= audio[0]->dts_usec;
  681. output->highest_video_ts -= video->dts_usec;
  682. /* apply new offsets to all existing packet DTS/PTS values */
  683. for (size_t i = 0; i < output->interleaved_packets.num; i++) {
  684. struct encoder_packet *packet =
  685. &output->interleaved_packets.array[i];
  686. apply_interleaved_packet_offset(output, packet);
  687. }
  688. return true;
  689. }
  690. static inline void insert_interleaved_packet(struct obs_output *output,
  691. struct encoder_packet *out)
  692. {
  693. size_t idx;
  694. for (idx = 0; idx < output->interleaved_packets.num; idx++) {
  695. struct encoder_packet *cur_packet;
  696. cur_packet = output->interleaved_packets.array + idx;
  697. if (out->dts_usec < cur_packet->dts_usec)
  698. break;
  699. }
  700. da_insert(output->interleaved_packets, idx, out);
  701. }
  702. static void resort_interleaved_packets(struct obs_output *output)
  703. {
  704. DARRAY(struct encoder_packet) old_array;
  705. old_array.da = output->interleaved_packets.da;
  706. memset(&output->interleaved_packets, 0,
  707. sizeof(output->interleaved_packets));
  708. for (size_t i = 0; i < old_array.num; i++)
  709. insert_interleaved_packet(output, &old_array.array[i]);
  710. da_free(old_array);
  711. }
  712. static void interleave_packets(void *data, struct encoder_packet *packet)
  713. {
  714. struct obs_output *output = data;
  715. struct encoder_packet out;
  716. bool was_started;
  717. if (packet->type == OBS_ENCODER_AUDIO)
  718. packet->track_idx = get_track_index(output, packet);
  719. pthread_mutex_lock(&output->interleaved_mutex);
  720. was_started = output->received_audio && output->received_video;
  721. obs_duplicate_encoder_packet(&out, packet);
  722. if (was_started)
  723. apply_interleaved_packet_offset(output, &out);
  724. else
  725. check_received(output, packet);
  726. insert_interleaved_packet(output, &out);
  727. set_higher_ts(output, &out);
  728. /* when both video and audio have been received, we're ready
  729. * to start sending out packets (one at a time) */
  730. if (output->received_audio && output->received_video) {
  731. if (!was_started) {
  732. prune_interleaved_packets(output);
  733. if (initialize_interleaved_packets(output)) {
  734. resort_interleaved_packets(output);
  735. send_interleaved(output);
  736. }
  737. } else {
  738. send_interleaved(output);
  739. }
  740. }
  741. pthread_mutex_unlock(&output->interleaved_mutex);
  742. }
  743. static void default_encoded_callback(void *param, struct encoder_packet *packet)
  744. {
  745. struct obs_output *output = param;
  746. if (packet->type == OBS_ENCODER_AUDIO)
  747. packet->track_idx = get_track_index(output, packet);
  748. if (!output->stopped)
  749. output->info.encoded_packet(output->context.data, packet);
  750. if (packet->type == OBS_ENCODER_VIDEO)
  751. output->total_frames++;
  752. }
  753. static void default_raw_video_callback(void *param, struct video_data *frame)
  754. {
  755. struct obs_output *output = param;
  756. if (!output->stopped)
  757. output->info.raw_video(output->context.data, frame);
  758. output->total_frames++;
  759. }
  760. static void default_raw_audio_callback(void *param, size_t mix_idx,
  761. struct audio_data *frames)
  762. {
  763. struct obs_output *output = param;
  764. if (!output->stopped)
  765. output->info.raw_audio(output->context.data, frames);
  766. UNUSED_PARAMETER(mix_idx);
  767. }
  768. static inline void start_audio_encoders(struct obs_output *output,
  769. encoded_callback_t encoded_callback)
  770. {
  771. size_t num_mixes = num_audio_mixes(output);
  772. for (size_t i = 0; i < num_mixes; i++) {
  773. obs_encoder_start(output->audio_encoders[i],
  774. encoded_callback, output);
  775. }
  776. }
  777. static void hook_data_capture(struct obs_output *output, bool encoded,
  778. bool has_video, bool has_audio)
  779. {
  780. encoded_callback_t encoded_callback;
  781. if (encoded) {
  782. output->received_audio = false;
  783. output->received_video = false;
  784. output->highest_audio_ts = 0;
  785. output->highest_video_ts = 0;
  786. output->video_offset = 0;
  787. for (size_t i = 0; i < MAX_AUDIO_MIXES; i++)
  788. output->audio_offsets[0] = 0;
  789. free_packets(output);
  790. encoded_callback = (has_video && has_audio) ?
  791. interleave_packets : default_encoded_callback;
  792. if (has_video)
  793. obs_encoder_start(output->video_encoder,
  794. encoded_callback, output);
  795. if (has_audio)
  796. start_audio_encoders(output, encoded_callback);
  797. } else {
  798. if (has_video)
  799. video_output_connect(output->video,
  800. get_video_conversion(output),
  801. default_raw_video_callback, output);
  802. if (has_audio)
  803. audio_output_connect(output->audio, output->mixer_idx,
  804. get_audio_conversion(output),
  805. default_raw_audio_callback, output);
  806. }
  807. }
  808. static inline void do_output_signal(struct obs_output *output,
  809. const char *signal)
  810. {
  811. struct calldata params = {0};
  812. calldata_set_ptr(&params, "output", output);
  813. signal_handler_signal(output->context.signals, signal, &params);
  814. calldata_free(&params);
  815. }
  816. static inline void signal_start(struct obs_output *output)
  817. {
  818. do_output_signal(output, "start");
  819. }
  820. static inline void signal_reconnect(struct obs_output *output)
  821. {
  822. struct calldata params = {0};
  823. calldata_set_int(&params, "timeout_sec",
  824. output->reconnect_retry_cur_sec);
  825. calldata_set_ptr(&params, "output", output);
  826. signal_handler_signal(output->context.signals, "reconnect", &params);
  827. calldata_free(&params);
  828. }
  829. static inline void signal_reconnect_success(struct obs_output *output)
  830. {
  831. do_output_signal(output, "reconnect_success");
  832. }
  833. static inline void signal_stop(struct obs_output *output, int code)
  834. {
  835. struct calldata params = {0};
  836. calldata_set_int(&params, "code", code);
  837. calldata_set_ptr(&params, "output", output);
  838. signal_handler_signal(output->context.signals, "stop", &params);
  839. calldata_free(&params);
  840. }
  841. static inline void convert_flags(const struct obs_output *output,
  842. uint32_t flags, bool *encoded, bool *has_video, bool *has_audio,
  843. bool *has_service)
  844. {
  845. *encoded = (output->info.flags & OBS_OUTPUT_ENCODED) != 0;
  846. if (!flags)
  847. flags = output->info.flags;
  848. else
  849. flags &= output->info.flags;
  850. *has_video = (flags & OBS_OUTPUT_VIDEO) != 0;
  851. *has_audio = (flags & OBS_OUTPUT_AUDIO) != 0;
  852. *has_service = (flags & OBS_OUTPUT_SERVICE) != 0;
  853. }
  854. bool obs_output_can_begin_data_capture(const obs_output_t *output,
  855. uint32_t flags)
  856. {
  857. bool encoded, has_video, has_audio, has_service;
  858. if (!output) return false;
  859. if (output->active) return false;
  860. convert_flags(output, flags, &encoded, &has_video, &has_audio,
  861. &has_service);
  862. return can_begin_data_capture(output, encoded, has_video, has_audio,
  863. has_service);
  864. }
  865. static inline bool initialize_audio_encoders(obs_output_t *output,
  866. size_t num_mixes)
  867. {
  868. for (size_t i = 0; i < num_mixes; i++) {
  869. if (!obs_encoder_initialize(output->audio_encoders[i])) {
  870. return false;
  871. }
  872. }
  873. return true;
  874. }
  875. static inline bool pair_encoders(obs_output_t *output, size_t num_mixes)
  876. {
  877. if (num_mixes == 1 &&
  878. !output->audio_encoders[0]->active &&
  879. !output->video_encoder->active &&
  880. !output->video_encoder->paired_encoder &&
  881. !output->audio_encoders[0]->paired_encoder) {
  882. output->audio_encoders[0]->wait_for_video = true;
  883. output->audio_encoders[0]->paired_encoder =
  884. output->video_encoder;
  885. output->video_encoder->paired_encoder =
  886. output->audio_encoders[0];
  887. }
  888. return true;
  889. }
  890. bool obs_output_initialize_encoders(obs_output_t *output, uint32_t flags)
  891. {
  892. bool encoded, has_video, has_audio, has_service;
  893. size_t num_mixes = num_audio_mixes(output);
  894. if (!output) return false;
  895. if (output->active) return false;
  896. convert_flags(output, flags, &encoded, &has_video, &has_audio,
  897. &has_service);
  898. if (!encoded)
  899. return false;
  900. if (has_service && !obs_service_initialize(output->service, output))
  901. return false;
  902. if (has_video && !obs_encoder_initialize(output->video_encoder))
  903. return false;
  904. if (has_audio && !initialize_audio_encoders(output, num_mixes))
  905. return false;
  906. if (has_video && has_audio) {
  907. if (!pair_encoders(output, num_mixes)) {
  908. return false;
  909. }
  910. }
  911. return true;
  912. }
  913. bool obs_output_begin_data_capture(obs_output_t *output, uint32_t flags)
  914. {
  915. bool encoded, has_video, has_audio, has_service;
  916. if (!output) return false;
  917. if (output->active) return false;
  918. output->total_frames = 0;
  919. convert_flags(output, flags, &encoded, &has_video, &has_audio,
  920. &has_service);
  921. if (!can_begin_data_capture(output, encoded, has_video, has_audio,
  922. has_service))
  923. return false;
  924. hook_data_capture(output, encoded, has_video, has_audio);
  925. if (has_service)
  926. obs_service_activate(output->service);
  927. output->active = true;
  928. if (output->reconnecting) {
  929. signal_reconnect_success(output);
  930. output->reconnecting = false;
  931. } else {
  932. signal_start(output);
  933. }
  934. return true;
  935. }
  936. static inline void stop_audio_encoders(obs_output_t *output,
  937. encoded_callback_t encoded_callback)
  938. {
  939. size_t num_mixes = num_audio_mixes(output);
  940. for (size_t i = 0; i < num_mixes; i++) {
  941. obs_encoder_stop(output->audio_encoders[i],
  942. encoded_callback, output);
  943. }
  944. }
  945. void obs_output_end_data_capture(obs_output_t *output)
  946. {
  947. bool encoded, has_video, has_audio, has_service;
  948. encoded_callback_t encoded_callback;
  949. if (!output) return;
  950. if (!output->active) return;
  951. convert_flags(output, 0, &encoded, &has_video, &has_audio,
  952. &has_service);
  953. if (encoded) {
  954. encoded_callback = (has_video && has_audio) ?
  955. interleave_packets : default_encoded_callback;
  956. if (has_video)
  957. obs_encoder_stop(output->video_encoder,
  958. encoded_callback, output);
  959. if (has_audio)
  960. stop_audio_encoders(output, encoded_callback);
  961. } else {
  962. if (has_video)
  963. video_output_disconnect(output->video,
  964. default_raw_video_callback, output);
  965. if (has_audio)
  966. audio_output_disconnect(output->audio,
  967. output->mixer_idx,
  968. default_raw_audio_callback, output);
  969. }
  970. if (has_service)
  971. obs_service_deactivate(output->service, false);
  972. output->active = false;
  973. }
  974. static void *reconnect_thread(void *param)
  975. {
  976. struct obs_output *output = param;
  977. unsigned long ms = output->reconnect_retry_cur_sec * 1000;
  978. output->reconnect_thread_active = true;
  979. if (os_event_timedwait(output->reconnect_stop_event, ms) == ETIMEDOUT)
  980. obs_output_start(output);
  981. if (os_event_try(output->reconnect_stop_event) == EAGAIN)
  982. pthread_detach(output->reconnect_thread);
  983. output->reconnect_thread_active = false;
  984. return NULL;
  985. }
  986. static void output_reconnect(struct obs_output *output)
  987. {
  988. int ret;
  989. if (!output->reconnecting) {
  990. output->reconnect_retry_cur_sec = output->reconnect_retry_sec;
  991. output->reconnect_retries = 0;
  992. }
  993. if (output->reconnect_retries >= output->reconnect_retry_max) {
  994. output->reconnecting = false;
  995. signal_stop(output, OBS_OUTPUT_DISCONNECTED);
  996. return;
  997. }
  998. if (!output->reconnecting) {
  999. output->reconnecting = true;
  1000. os_event_reset(output->reconnect_stop_event);
  1001. }
  1002. if (output->reconnect_retries) {
  1003. output->reconnect_retry_cur_sec *= 2;
  1004. }
  1005. output->reconnect_retries++;
  1006. ret = pthread_create(&output->reconnect_thread, NULL,
  1007. &reconnect_thread, output);
  1008. if (ret < 0) {
  1009. blog(LOG_WARNING, "Failed to create reconnect thread");
  1010. output->reconnecting = false;
  1011. signal_stop(output, OBS_OUTPUT_DISCONNECTED);
  1012. } else {
  1013. blog(LOG_INFO, "Output '%s': Reconnecting in %d seconds..",
  1014. output->context.name,
  1015. output->reconnect_retry_sec);
  1016. signal_reconnect(output);
  1017. }
  1018. }
  1019. void obs_output_signal_stop(obs_output_t *output, int code)
  1020. {
  1021. if (!output)
  1022. return;
  1023. obs_output_end_data_capture(output);
  1024. if ((output->reconnecting && code != OBS_OUTPUT_SUCCESS) ||
  1025. code == OBS_OUTPUT_DISCONNECTED)
  1026. output_reconnect(output);
  1027. else
  1028. signal_stop(output, code);
  1029. }
  1030. void obs_output_addref(obs_output_t *output)
  1031. {
  1032. if (!output)
  1033. return;
  1034. obs_ref_addref(&output->control->ref);
  1035. }
  1036. void obs_output_release(obs_output_t *output)
  1037. {
  1038. if (!output)
  1039. return;
  1040. obs_weak_output_t *control = output->control;
  1041. if (obs_ref_release(&control->ref)) {
  1042. // The order of operations is important here since
  1043. // get_context_by_name in obs.c relies on weak refs
  1044. // being alive while the context is listed
  1045. obs_output_destroy(output);
  1046. obs_weak_output_release(control);
  1047. }
  1048. }
  1049. void obs_weak_output_addref(obs_weak_output_t *weak)
  1050. {
  1051. if (!weak)
  1052. return;
  1053. obs_weak_ref_addref(&weak->ref);
  1054. }
  1055. void obs_weak_output_release(obs_weak_output_t *weak)
  1056. {
  1057. if (!weak)
  1058. return;
  1059. if (obs_weak_ref_release(&weak->ref))
  1060. bfree(weak);
  1061. }
  1062. obs_output_t *obs_output_get_ref(obs_output_t *output)
  1063. {
  1064. if (!output)
  1065. return NULL;
  1066. return obs_weak_output_get_output(output->control);
  1067. }
  1068. obs_weak_output_t *obs_output_get_weak_output(obs_output_t *output)
  1069. {
  1070. if (!output)
  1071. return NULL;
  1072. obs_weak_output_t *weak = output->control;
  1073. obs_weak_output_addref(weak);
  1074. return weak;
  1075. }
  1076. obs_output_t *obs_weak_output_get_output(obs_weak_output_t *weak)
  1077. {
  1078. if (!weak)
  1079. return NULL;
  1080. if (obs_weak_ref_get_ref(&weak->ref))
  1081. return weak->output;
  1082. return NULL;
  1083. }
  1084. bool obs_weak_output_references_output(obs_weak_output_t *weak,
  1085. obs_output_t *output)
  1086. {
  1087. return weak && output && weak->output == output;
  1088. }