obs-output.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  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 "obs.h"
  15. #include "obs-internal.h"
  16. static inline void signal_stop(struct obs_output *output, int code);
  17. static inline const struct obs_output_info *find_output(const char *id)
  18. {
  19. size_t i;
  20. for (i = 0; i < obs->output_types.num; i++)
  21. if (strcmp(obs->output_types.array[i].id, id) == 0)
  22. return obs->output_types.array+i;
  23. return NULL;
  24. }
  25. const char *obs_output_getdisplayname(const char *id)
  26. {
  27. const struct obs_output_info *info = find_output(id);
  28. return (info != NULL) ? info->getname() : NULL;
  29. }
  30. static const char *output_signals[] = {
  31. "void start(ptr output)",
  32. "void stop(ptr output, int code)",
  33. "void reconnect(ptr output)",
  34. "void reconnect_success(ptr output)",
  35. NULL
  36. };
  37. static bool init_output_handlers(struct obs_output *output, const char *name,
  38. obs_data_t settings)
  39. {
  40. if (!obs_context_data_init(&output->context, settings, name))
  41. return false;
  42. signal_handler_add_array(output->context.signals, output_signals);
  43. return true;
  44. }
  45. obs_output_t obs_output_create(const char *id, const char *name,
  46. obs_data_t settings)
  47. {
  48. const struct obs_output_info *info = find_output(id);
  49. struct obs_output *output;
  50. if (!info) {
  51. blog(LOG_ERROR, "Output '%s' not found", id);
  52. return NULL;
  53. }
  54. output = bzalloc(sizeof(struct obs_output));
  55. pthread_mutex_init_value(&output->interleaved_mutex);
  56. if (pthread_mutex_init(&output->interleaved_mutex, NULL) != 0)
  57. goto fail;
  58. if (!init_output_handlers(output, name, settings))
  59. goto fail;
  60. output->info = *info;
  61. output->video = obs_video();
  62. output->audio = obs_audio();
  63. if (output->info.defaults)
  64. output->info.defaults(output->context.settings);
  65. output->context.data = info->create(output->context.settings, output);
  66. if (!output->context.data)
  67. goto fail;
  68. output->valid = true;
  69. obs_context_data_insert(&output->context,
  70. &obs->data.outputs_mutex,
  71. &obs->data.first_output);
  72. return output;
  73. fail:
  74. obs_output_destroy(output);
  75. return NULL;
  76. }
  77. static inline void free_packets(struct obs_output *output)
  78. {
  79. for (size_t i = 0; i < output->interleaved_packets.num; i++)
  80. obs_free_encoder_packet(output->interleaved_packets.array+i);
  81. da_free(output->interleaved_packets);
  82. }
  83. void obs_output_destroy(obs_output_t output)
  84. {
  85. if (output) {
  86. obs_context_data_remove(&output->context);
  87. if (output->valid && output->active)
  88. output->info.stop(output->context.data);
  89. if (output->service)
  90. output->service->output = NULL;
  91. free_packets(output);
  92. if (output->context.data)
  93. output->info.destroy(output->context.data);
  94. if (output->video_encoder) {
  95. obs_encoder_remove_output(output->video_encoder,
  96. output);
  97. }
  98. if (output->audio_encoder) {
  99. obs_encoder_remove_output(output->audio_encoder,
  100. output);
  101. }
  102. pthread_mutex_destroy(&output->interleaved_mutex);
  103. obs_context_data_free(&output->context);
  104. bfree(output);
  105. }
  106. }
  107. bool obs_output_start(obs_output_t output)
  108. {
  109. return (output != NULL) ?
  110. output->info.start(output->context.data) : false;
  111. }
  112. void obs_output_stop(obs_output_t output)
  113. {
  114. if (output) {
  115. output->info.stop(output->context.data);
  116. signal_stop(output, OBS_OUTPUT_SUCCESS);
  117. }
  118. }
  119. bool obs_output_active(obs_output_t output)
  120. {
  121. return (output != NULL) ? output->active : false;
  122. }
  123. static inline obs_data_t get_defaults(const struct obs_output_info *info)
  124. {
  125. obs_data_t settings = obs_data_create();
  126. if (info->defaults)
  127. info->defaults(settings);
  128. return settings;
  129. }
  130. obs_data_t obs_output_defaults(const char *id)
  131. {
  132. const struct obs_output_info *info = find_output(id);
  133. return (info) ? get_defaults(info) : NULL;
  134. }
  135. obs_properties_t obs_get_output_properties(const char *id)
  136. {
  137. const struct obs_output_info *info = find_output(id);
  138. if (info && info->properties) {
  139. obs_data_t defaults = get_defaults(info);
  140. obs_properties_t properties;
  141. properties = info->properties();
  142. obs_properties_apply_settings(properties, defaults);
  143. obs_data_release(defaults);
  144. return properties;
  145. }
  146. return NULL;
  147. }
  148. obs_properties_t obs_output_properties(obs_output_t output)
  149. {
  150. if (output && output->info.properties) {
  151. obs_properties_t props;
  152. props = output->info.properties();
  153. obs_properties_apply_settings(props, output->context.settings);
  154. return props;
  155. }
  156. return NULL;
  157. }
  158. void obs_output_update(obs_output_t output, obs_data_t settings)
  159. {
  160. if (!output) return;
  161. obs_data_apply(output->context.settings, settings);
  162. if (output->info.update)
  163. output->info.update(output->context.data,
  164. output->context.settings);
  165. }
  166. obs_data_t obs_output_get_settings(obs_output_t output)
  167. {
  168. if (!output)
  169. return NULL;
  170. obs_data_addref(output->context.settings);
  171. return output->context.settings;
  172. }
  173. bool obs_output_canpause(obs_output_t output)
  174. {
  175. return output ? (output->info.pause != NULL) : false;
  176. }
  177. void obs_output_pause(obs_output_t output)
  178. {
  179. if (output && output->info.pause)
  180. output->info.pause(output->context.data);
  181. }
  182. signal_handler_t obs_output_signalhandler(obs_output_t output)
  183. {
  184. return output ? output->context.signals : NULL;
  185. }
  186. proc_handler_t obs_output_prochandler(obs_output_t output)
  187. {
  188. return output ? output->context.procs : NULL;
  189. }
  190. void obs_output_set_media(obs_output_t output, video_t video, audio_t audio)
  191. {
  192. if (!output)
  193. return;
  194. output->video = video;
  195. output->audio = audio;
  196. }
  197. video_t obs_output_video(obs_output_t output)
  198. {
  199. return output ? output->video : NULL;
  200. }
  201. audio_t obs_output_audio(obs_output_t output)
  202. {
  203. return output ? output->audio : NULL;
  204. }
  205. void obs_output_remove_encoder(struct obs_output *output,
  206. struct obs_encoder *encoder)
  207. {
  208. if (!output) return;
  209. if (output->video_encoder == encoder)
  210. output->video_encoder = NULL;
  211. else if (output->audio_encoder == encoder)
  212. output->audio_encoder = NULL;
  213. }
  214. void obs_output_set_video_encoder(obs_output_t output, obs_encoder_t encoder)
  215. {
  216. if (!output) return;
  217. if (output->video_encoder == encoder) return;
  218. if (encoder && encoder->info.type != OBS_ENCODER_VIDEO) return;
  219. obs_encoder_remove_output(encoder, output);
  220. obs_encoder_add_output(encoder, output);
  221. output->video_encoder = encoder;
  222. }
  223. void obs_output_set_audio_encoder(obs_output_t output, obs_encoder_t encoder)
  224. {
  225. if (!output) return;
  226. if (output->audio_encoder == encoder) return;
  227. if (encoder && encoder->info.type != OBS_ENCODER_AUDIO) return;
  228. obs_encoder_remove_output(encoder, output);
  229. obs_encoder_add_output(encoder, output);
  230. output->audio_encoder = encoder;
  231. }
  232. obs_encoder_t obs_output_get_video_encoder(obs_output_t output)
  233. {
  234. return output ? output->video_encoder : NULL;
  235. }
  236. obs_encoder_t obs_output_get_audio_encoder(obs_output_t output)
  237. {
  238. return output ? output->audio_encoder : NULL;
  239. }
  240. void obs_output_set_service(obs_output_t output, obs_service_t service)
  241. {
  242. if (!output || output->active || !service || service->active) return;
  243. if (service->output)
  244. service->output->service = NULL;
  245. output->service = service;
  246. service->output = output;
  247. }
  248. obs_service_t obs_output_get_service(obs_output_t output)
  249. {
  250. return output ? output->service : NULL;
  251. }
  252. void obs_output_set_video_conversion(obs_output_t output,
  253. const struct video_scale_info *conversion)
  254. {
  255. if (!output || !conversion) return;
  256. output->video_conversion = *conversion;
  257. output->video_conversion_set = true;
  258. }
  259. void obs_output_set_audio_conversion(obs_output_t output,
  260. const struct audio_convert_info *conversion)
  261. {
  262. if (!output || !conversion) return;
  263. output->audio_conversion = *conversion;
  264. output->audio_conversion_set = true;
  265. }
  266. static bool can_begin_data_capture(struct obs_output *output, bool encoded,
  267. bool has_video, bool has_audio, bool has_service)
  268. {
  269. if (has_video) {
  270. if (encoded) {
  271. if (!output->video_encoder)
  272. return false;
  273. } else {
  274. if (!output->video)
  275. return false;
  276. }
  277. }
  278. if (has_audio) {
  279. if (encoded) {
  280. if (!output->audio_encoder)
  281. return false;
  282. } else {
  283. if (!output->audio)
  284. return false;
  285. }
  286. }
  287. if (has_service && !output->service)
  288. return false;
  289. return true;
  290. }
  291. static inline struct video_scale_info *get_video_conversion(
  292. struct obs_output *output)
  293. {
  294. return output->video_conversion_set ? &output->video_conversion : NULL;
  295. }
  296. static inline struct audio_convert_info *get_audio_conversion(
  297. struct obs_output *output)
  298. {
  299. return output->audio_conversion_set ? &output->audio_conversion : NULL;
  300. }
  301. static bool prepare_interleaved_packet(struct obs_output *output,
  302. struct encoder_packet *out, struct encoder_packet *in)
  303. {
  304. int64_t offset;
  305. /* audio and video need to start at timestamp 0, and the encoders
  306. * may not currently be at 0 when we get data. so, we store the
  307. * current dts as offset and subtract that value from the dts/pts
  308. * of the output packet. */
  309. if (in->type == OBS_ENCODER_VIDEO) {
  310. if (!output->received_video) {
  311. output->first_video_ts = in->dts_usec;
  312. output->video_offset = in->dts;
  313. output->received_video = true;
  314. }
  315. offset = output->video_offset;
  316. } else{
  317. /* don't accept audio that's before the first video timestamp */
  318. if (!output->received_video ||
  319. in->dts_usec < output->first_video_ts)
  320. return false;
  321. if (!output->received_audio) {
  322. output->audio_offset = in->dts;
  323. output->received_audio = true;
  324. }
  325. offset = output->audio_offset;
  326. }
  327. obs_duplicate_encoder_packet(out, in);
  328. out->dts -= offset;
  329. out->pts -= offset;
  330. /* convert the newly adjusted dts to relative dts time to ensure proper
  331. * interleaving. if we're using an audio encoder that's already been
  332. * started on another output, then the first audio packet may not be
  333. * quite perfectly synced up in terms of system time (and there's
  334. * nothing we can really do about that), but it will always at least be
  335. * within a 23ish millisecond threshold (at least for AAC) */
  336. out->dts_usec = packet_dts_usec(out);
  337. return true;
  338. }
  339. static inline bool has_higher_opposing_ts(struct obs_output *output,
  340. struct encoder_packet *packet)
  341. {
  342. if (packet->type == OBS_ENCODER_VIDEO)
  343. return output->highest_audio_ts > packet->dts_usec;
  344. else
  345. return output->highest_video_ts > packet->dts_usec;
  346. }
  347. static inline void send_interleaved(struct obs_output *output)
  348. {
  349. struct encoder_packet out = output->interleaved_packets.array[0];
  350. /* do not send an interleaved packet if there's no packet of the
  351. * opposing type of a higher timstamp in the interleave buffer.
  352. * this ensures that the timestamps are monotonic */
  353. if (!has_higher_opposing_ts(output, &out))
  354. return;
  355. da_erase(output->interleaved_packets, 0);
  356. output->info.encoded_packet(output->context.data, &out);
  357. obs_free_encoder_packet(&out);
  358. }
  359. static inline void set_higher_ts(struct obs_output *output,
  360. struct encoder_packet *packet)
  361. {
  362. if (packet->type == OBS_ENCODER_VIDEO) {
  363. if (output->highest_video_ts < packet->dts_usec)
  364. output->highest_video_ts = packet->dts_usec;
  365. } else {
  366. if (output->highest_audio_ts < packet->dts_usec)
  367. output->highest_audio_ts = packet->dts_usec;
  368. }
  369. }
  370. static void interleave_packets(void *data, struct encoder_packet *packet)
  371. {
  372. struct obs_output *output = data;
  373. struct encoder_packet out;
  374. size_t idx;
  375. pthread_mutex_lock(&output->interleaved_mutex);
  376. if (prepare_interleaved_packet(output, &out, packet)) {
  377. for (idx = 0; idx < output->interleaved_packets.num; idx++) {
  378. struct encoder_packet *cur_packet;
  379. cur_packet = output->interleaved_packets.array + idx;
  380. if (out.dts_usec < cur_packet->dts_usec)
  381. break;
  382. }
  383. da_insert(output->interleaved_packets, idx, &out);
  384. set_higher_ts(output, &out);
  385. /* when both video and audio have been received, we're ready
  386. * to start sending out packets (one at a time) */
  387. if (output->received_audio && output->received_video)
  388. send_interleaved(output);
  389. }
  390. pthread_mutex_unlock(&output->interleaved_mutex);
  391. }
  392. static void hook_data_capture(struct obs_output *output, bool encoded,
  393. bool has_video, bool has_audio)
  394. {
  395. void (*encoded_callback)(void *data, struct encoder_packet *packet);
  396. void *param;
  397. if (encoded) {
  398. output->received_video = false;
  399. output->received_video = false;
  400. output->highest_audio_ts = 0;
  401. output->highest_video_ts = 0;
  402. free_packets(output);
  403. encoded_callback = (has_video && has_audio) ?
  404. interleave_packets : output->info.encoded_packet;
  405. param = (has_video && has_audio) ?
  406. output : output->context.data;
  407. if (has_video)
  408. obs_encoder_start(output->video_encoder,
  409. encoded_callback, param);
  410. if (has_audio)
  411. obs_encoder_start(output->audio_encoder,
  412. encoded_callback, param);
  413. } else {
  414. if (has_video)
  415. video_output_connect(output->video,
  416. get_video_conversion(output),
  417. output->info.raw_video,
  418. output->context.data);
  419. if (has_audio)
  420. audio_output_connect(output->audio,
  421. get_audio_conversion(output),
  422. output->info.raw_audio,
  423. output->context.data);
  424. }
  425. }
  426. static inline void signal_start(struct obs_output *output)
  427. {
  428. struct calldata params = {0};
  429. calldata_setptr(&params, "output", output);
  430. signal_handler_signal(output->context.signals, "start", &params);
  431. calldata_free(&params);
  432. }
  433. static inline void signal_stop(struct obs_output *output, int code)
  434. {
  435. struct calldata params = {0};
  436. calldata_setint(&params, "code", code);
  437. calldata_setptr(&params, "output", output);
  438. signal_handler_signal(output->context.signals, "stop", &params);
  439. calldata_free(&params);
  440. }
  441. static inline void convert_flags(struct obs_output *output, uint32_t flags,
  442. bool *encoded, bool *has_video, bool *has_audio,
  443. bool *has_service)
  444. {
  445. *encoded = (output->info.flags & OBS_OUTPUT_ENCODED) != 0;
  446. if (!flags)
  447. flags = output->info.flags;
  448. else
  449. flags &= output->info.flags;
  450. *has_video = (flags & OBS_OUTPUT_VIDEO) != 0;
  451. *has_audio = (flags & OBS_OUTPUT_AUDIO) != 0;
  452. *has_service = (flags & OBS_OUTPUT_SERVICE) != 0;
  453. }
  454. bool obs_output_can_begin_data_capture(obs_output_t output, uint32_t flags)
  455. {
  456. bool encoded, has_video, has_audio, has_service;
  457. if (!output) return false;
  458. if (output->active) return false;
  459. convert_flags(output, flags, &encoded, &has_video, &has_audio,
  460. &has_service);
  461. return can_begin_data_capture(output, encoded, has_video, has_audio,
  462. has_service);
  463. }
  464. bool obs_output_initialize_encoders(obs_output_t output, uint32_t flags)
  465. {
  466. bool encoded, has_video, has_audio, has_service;
  467. if (!output) return false;
  468. if (output->active) return false;
  469. convert_flags(output, flags, &encoded, &has_video, &has_audio,
  470. &has_service);
  471. if (!encoded)
  472. return false;
  473. if (has_service && !obs_service_initialize(output->service, output))
  474. return false;
  475. if (has_video && !obs_encoder_initialize(output->video_encoder))
  476. return false;
  477. if (has_audio && !obs_encoder_initialize(output->audio_encoder))
  478. return false;
  479. if (has_video && has_audio && !output->audio_encoder->active &&
  480. !output->video_encoder->active) {
  481. output->audio_encoder->wait_for_video = true;
  482. output->video_encoder->paired_encoder = output->audio_encoder;
  483. output->audio_encoder->paired_encoder = output->video_encoder;
  484. }
  485. return true;
  486. }
  487. bool obs_output_begin_data_capture(obs_output_t output, uint32_t flags)
  488. {
  489. bool encoded, has_video, has_audio, has_service;
  490. if (!output) return false;
  491. if (output->active) return false;
  492. convert_flags(output, flags, &encoded, &has_video, &has_audio,
  493. &has_service);
  494. if (!can_begin_data_capture(output, encoded, has_video, has_audio,
  495. has_service))
  496. return false;
  497. hook_data_capture(output, encoded, has_video, has_audio);
  498. if (has_service)
  499. obs_service_activate(output->service);
  500. output->active = true;
  501. signal_start(output);
  502. return true;
  503. }
  504. void obs_output_end_data_capture(obs_output_t output)
  505. {
  506. bool encoded, has_video, has_audio, has_service;
  507. void (*encoded_callback)(void *data, struct encoder_packet *packet);
  508. void *param;
  509. if (!output) return;
  510. if (!output->active) return;
  511. convert_flags(output, 0, &encoded, &has_video, &has_audio,
  512. &has_service);
  513. if (encoded) {
  514. encoded_callback = (has_video && has_audio) ?
  515. interleave_packets : output->info.encoded_packet;
  516. param = (has_video && has_audio) ?
  517. output : output->context.data;
  518. if (has_video)
  519. obs_encoder_stop(output->video_encoder,
  520. encoded_callback, param);
  521. if (has_audio)
  522. obs_encoder_stop(output->audio_encoder,
  523. encoded_callback, param);
  524. } else {
  525. if (has_video)
  526. video_output_disconnect(output->video,
  527. output->info.raw_video,
  528. output->context.data);
  529. if (has_audio)
  530. audio_output_disconnect(output->audio,
  531. output->info.raw_audio,
  532. output->context.data);
  533. }
  534. if (has_service)
  535. obs_service_deactivate(output->service, false);
  536. output->active = false;
  537. }
  538. void obs_output_signal_stop(obs_output_t output, int code)
  539. {
  540. obs_output_end_data_capture(output);
  541. signal_stop(output, code);
  542. }