obs-output.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  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 const struct obs_output_info *find_output(const char *id)
  17. {
  18. size_t i;
  19. for (i = 0; i < obs->output_types.num; i++)
  20. if (strcmp(obs->output_types.array[i].id, id) == 0)
  21. return obs->output_types.array+i;
  22. return NULL;
  23. }
  24. static const char *output_signals[] = {
  25. "void start(ptr output, int errorcode)",
  26. "void stop(ptr output)",
  27. NULL
  28. };
  29. static bool init_output_handlers(struct obs_output *output)
  30. {
  31. output->signals = signal_handler_create();
  32. if (!output->signals)
  33. return false;
  34. output->procs = proc_handler_create();
  35. if (!output->procs)
  36. return false;
  37. signal_handler_add_array(output->signals, output_signals);
  38. return true;
  39. }
  40. obs_output_t obs_output_create(const char *id, const char *name,
  41. obs_data_t settings)
  42. {
  43. const struct obs_output_info *info = find_output(id);
  44. struct obs_output *output;
  45. if (!info) {
  46. blog(LOG_ERROR, "Output '%s' not found", id);
  47. return NULL;
  48. }
  49. output = bzalloc(sizeof(struct obs_output));
  50. pthread_mutex_init_value(&output->interleaved_mutex);
  51. if (pthread_mutex_init(&output->interleaved_mutex, NULL) != 0)
  52. goto fail;
  53. if (!init_output_handlers(output))
  54. goto fail;
  55. output->info = *info;
  56. output->video = obs_video();
  57. output->audio = obs_audio();
  58. output->settings = obs_data_newref(settings);
  59. if (output->info.defaults)
  60. output->info.defaults(output->settings);
  61. output->data = info->create(output->settings, output);
  62. if (!output->data)
  63. goto fail;
  64. output->name = bstrdup(name);
  65. pthread_mutex_lock(&obs->data.outputs_mutex);
  66. da_push_back(obs->data.outputs, &output);
  67. pthread_mutex_unlock(&obs->data.outputs_mutex);
  68. output->valid = true;
  69. return output;
  70. fail:
  71. obs_output_destroy(output);
  72. return NULL;
  73. }
  74. static inline void free_il_packet(struct il_packet *data)
  75. {
  76. obs_free_encoder_packet(&data->packet);
  77. }
  78. static inline void free_packets(struct obs_output *output)
  79. {
  80. for (size_t i = 0; i < output->interleaved_packets.num; i++)
  81. free_il_packet(output->interleaved_packets.array+i);
  82. da_free(output->interleaved_packets);
  83. }
  84. void obs_output_destroy(obs_output_t output)
  85. {
  86. if (output) {
  87. if (output->valid) {
  88. if (output->active)
  89. output->info.stop(output->data);
  90. pthread_mutex_lock(&obs->data.outputs_mutex);
  91. da_erase_item(obs->data.outputs, &output);
  92. pthread_mutex_unlock(&obs->data.outputs_mutex);
  93. }
  94. free_packets(output);
  95. if (output->data)
  96. output->info.destroy(output->data);
  97. signal_handler_destroy(output->signals);
  98. proc_handler_destroy(output->procs);
  99. obs_data_release(output->settings);
  100. pthread_mutex_destroy(&output->interleaved_mutex);
  101. bfree(output->name);
  102. bfree(output);
  103. }
  104. }
  105. bool obs_output_start(obs_output_t output)
  106. {
  107. return (output != NULL) ? output->info.start(output->data) : false;
  108. }
  109. void obs_output_stop(obs_output_t output)
  110. {
  111. if (output)
  112. output->info.stop(output->data);
  113. }
  114. bool obs_output_active(obs_output_t output)
  115. {
  116. return (output != NULL) ? output->active : false;
  117. }
  118. static inline obs_data_t get_defaults(const struct obs_output_info *info)
  119. {
  120. obs_data_t settings = obs_data_create();
  121. if (info->defaults)
  122. info->defaults(settings);
  123. return settings;
  124. }
  125. obs_data_t obs_output_defaults(const char *id)
  126. {
  127. const struct obs_output_info *info = find_output(id);
  128. return (info) ? get_defaults(info) : NULL;
  129. }
  130. obs_properties_t obs_get_output_properties(const char *id, const char *locale)
  131. {
  132. const struct obs_output_info *info = find_output(id);
  133. if (info && info->properties) {
  134. obs_data_t defaults = get_defaults(info);
  135. obs_properties_t properties;
  136. properties = info->properties(locale);
  137. obs_properties_apply_settings(properties, defaults);
  138. obs_data_release(defaults);
  139. return properties;
  140. }
  141. return NULL;
  142. }
  143. obs_properties_t obs_output_properties(obs_output_t output, const char *locale)
  144. {
  145. if (output && output->info.properties) {
  146. obs_properties_t props;
  147. props = output->info.properties(locale);
  148. obs_properties_apply_settings(props, output->settings);
  149. return props;
  150. }
  151. return NULL;
  152. }
  153. void obs_output_update(obs_output_t output, obs_data_t settings)
  154. {
  155. if (!output) return;
  156. obs_data_apply(output->settings, settings);
  157. if (output->info.update)
  158. output->info.update(output->data, output->settings);
  159. }
  160. obs_data_t obs_output_get_settings(obs_output_t output)
  161. {
  162. if (!output)
  163. return NULL;
  164. obs_data_addref(output->settings);
  165. return output->settings;
  166. }
  167. bool obs_output_canpause(obs_output_t output)
  168. {
  169. return output ? (output->info.pause != NULL) : false;
  170. }
  171. void obs_output_pause(obs_output_t output)
  172. {
  173. if (output && output->info.pause)
  174. output->info.pause(output->data);
  175. }
  176. signal_handler_t obs_output_signalhandler(obs_output_t output)
  177. {
  178. return output ? output->signals : NULL;
  179. }
  180. proc_handler_t obs_output_prochandler(obs_output_t output)
  181. {
  182. return output ? output->procs : NULL;
  183. }
  184. void obs_output_set_media(obs_output_t output, video_t video, audio_t audio)
  185. {
  186. if (!output)
  187. return;
  188. output->video = video;
  189. output->audio = audio;
  190. }
  191. video_t obs_output_video(obs_output_t output)
  192. {
  193. return output ? output->video : NULL;
  194. }
  195. audio_t obs_output_audio(obs_output_t output)
  196. {
  197. return output ? output->audio : NULL;
  198. }
  199. void obs_output_remove_encoder(struct obs_output *output,
  200. struct obs_encoder *encoder)
  201. {
  202. if (!output) return;
  203. if (output->video_encoder == encoder)
  204. output->video_encoder = NULL;
  205. else if (output->audio_encoder == encoder)
  206. output->audio_encoder = NULL;
  207. }
  208. void obs_output_set_video_encoder(obs_output_t output, obs_encoder_t encoder)
  209. {
  210. if (!output) return;
  211. if (output->video_encoder == encoder) return;
  212. if (encoder && encoder->info.type != OBS_ENCODER_VIDEO) return;
  213. obs_encoder_remove_output(encoder, output);
  214. obs_encoder_add_output(encoder, output);
  215. output->video_encoder = encoder;
  216. }
  217. void obs_output_set_audio_encoder(obs_output_t output, obs_encoder_t encoder)
  218. {
  219. if (!output) return;
  220. if (output->audio_encoder == encoder) return;
  221. if (encoder && encoder->info.type != OBS_ENCODER_AUDIO) return;
  222. obs_encoder_remove_output(encoder, output);
  223. obs_encoder_add_output(encoder, output);
  224. output->audio_encoder = encoder;
  225. }
  226. obs_encoder_t obs_output_get_video_encoder(obs_output_t output)
  227. {
  228. return output ? output->video_encoder : NULL;
  229. }
  230. obs_encoder_t obs_output_get_audio_encoder(obs_output_t output)
  231. {
  232. return output ? output->audio_encoder : NULL;
  233. }
  234. void obs_output_set_video_conversion(obs_output_t output,
  235. const struct video_scale_info *conversion)
  236. {
  237. if (!output || !conversion) return;
  238. output->video_conversion = *conversion;
  239. output->video_conversion_set = true;
  240. }
  241. void obs_output_set_audio_conversion(obs_output_t output,
  242. const struct audio_convert_info *conversion)
  243. {
  244. if (!output || !conversion) return;
  245. output->audio_conversion = *conversion;
  246. output->audio_conversion_set = true;
  247. }
  248. static bool can_begin_data_capture(struct obs_output *output, bool encoded,
  249. bool has_video, bool has_audio)
  250. {
  251. if (has_video) {
  252. if (encoded) {
  253. if (!output->video_encoder)
  254. return false;
  255. } else {
  256. if (!output->video)
  257. return false;
  258. }
  259. }
  260. if (has_audio) {
  261. if (encoded) {
  262. if (!output->audio_encoder)
  263. return false;
  264. } else {
  265. if (!output->audio)
  266. return false;
  267. }
  268. }
  269. return true;
  270. }
  271. static inline struct video_scale_info *get_video_conversion(
  272. struct obs_output *output)
  273. {
  274. return output->video_conversion_set ? &output->video_conversion : NULL;
  275. }
  276. static inline struct audio_convert_info *get_audio_conversion(
  277. struct obs_output *output)
  278. {
  279. return output->audio_conversion_set ? &output->audio_conversion : NULL;
  280. }
  281. #define MICROSECOND_DEN 1000000
  282. static inline int64_t convert_packet_dts(struct encoder_packet *packet)
  283. {
  284. return packet->dts * MICROSECOND_DEN / packet->timebase_den;
  285. }
  286. static bool prepare_interleaved_packet(struct obs_output *output,
  287. struct il_packet *out, struct encoder_packet *packet)
  288. {
  289. int64_t offset;
  290. out->input_ts_us = convert_packet_dts(packet);
  291. /* audio and video need to start at timestamp 0, and the encoders
  292. * may not currently be at 0 when we get data. so, we store the
  293. * current dts as offset and subtract that value from the dts/pts
  294. * of the output packet. */
  295. if (packet->type == OBS_ENCODER_VIDEO) {
  296. if (!output->received_video) {
  297. output->first_video_ts = out->input_ts_us;
  298. output->video_offset = packet->dts;
  299. output->received_video = true;
  300. }
  301. offset = output->video_offset;
  302. } else{
  303. /* don't accept audio that's before the first video timestamp */
  304. if (!output->received_video ||
  305. out->input_ts_us < output->first_video_ts)
  306. return false;
  307. if (!output->received_audio) {
  308. output->audio_offset = packet->dts;
  309. output->received_audio = true;
  310. }
  311. offset = output->audio_offset;
  312. }
  313. obs_duplicate_encoder_packet(&out->packet, packet);
  314. out->packet.dts -= offset;
  315. out->packet.pts -= offset;
  316. out->output_ts_us = convert_packet_dts(&out->packet);
  317. return true;
  318. }
  319. static inline void send_interleaved(struct obs_output *output)
  320. {
  321. struct il_packet out = output->interleaved_packets.array[0];
  322. da_erase(output->interleaved_packets, 0);
  323. output->info.encoded_packet(output->data, &out.packet);
  324. free_il_packet(&out);
  325. }
  326. static void interleave_packets(void *data, struct encoder_packet *packet)
  327. {
  328. struct obs_output *output = data;
  329. struct il_packet out;
  330. size_t idx;
  331. pthread_mutex_lock(&output->interleaved_mutex);
  332. if (!prepare_interleaved_packet(output, &out, packet)) {
  333. for (idx = 0; idx < output->interleaved_packets.num; idx++) {
  334. struct il_packet *cur_packet;
  335. cur_packet = output->interleaved_packets.array + idx;
  336. if (out.output_ts_us < cur_packet->output_ts_us)
  337. break;
  338. }
  339. da_insert(output->interleaved_packets, idx, &out);
  340. /* when both video and audio have been received, we're ready
  341. * to start sending out packets (one at a time) */
  342. if (output->received_audio && output->received_video)
  343. send_interleaved(output);
  344. }
  345. pthread_mutex_unlock(&output->interleaved_mutex);
  346. }
  347. static void hook_data_capture(struct obs_output *output, bool encoded,
  348. bool has_video, bool has_audio)
  349. {
  350. void (*encoded_callback)(void *data, struct encoder_packet *packet);
  351. void *param;
  352. if (encoded) {
  353. output->received_video = false;
  354. output->received_video = false;
  355. encoded_callback = (has_video && has_audio) ?
  356. interleave_packets : output->info.encoded_packet;
  357. param = (has_video && has_audio) ? output : output->data;
  358. if (has_video)
  359. obs_encoder_start(output->video_encoder,
  360. encoded_callback, param);
  361. if (has_audio)
  362. obs_encoder_start(output->audio_encoder,
  363. encoded_callback, param);
  364. } else {
  365. if (has_video)
  366. video_output_connect(output->video,
  367. get_video_conversion(output),
  368. output->info.raw_video,
  369. output->data);
  370. if (has_audio)
  371. audio_output_connect(output->audio,
  372. get_audio_conversion(output),
  373. output->info.raw_audio,
  374. output->data);
  375. }
  376. }
  377. static inline void signal_start(struct obs_output *output, int code)
  378. {
  379. struct calldata params = {0};
  380. calldata_setint(&params, "code", code);
  381. calldata_setptr(&params, "output", output);
  382. signal_handler_signal(output->signals, "start", &params);
  383. calldata_free(&params);
  384. }
  385. static inline void signal_stop(struct obs_output *output)
  386. {
  387. struct calldata params = {0};
  388. calldata_setptr(&params, "output", output);
  389. signal_handler_signal(output->signals, "stop", &params);
  390. calldata_free(&params);
  391. }
  392. static inline void convert_flags(struct obs_output *output, uint32_t flags,
  393. bool *encoded, bool *has_video, bool *has_audio)
  394. {
  395. *encoded = (output->info.flags & OBS_OUTPUT_ENCODED) != 0;
  396. if (!flags)
  397. flags = output->info.flags;
  398. else
  399. flags &= output->info.flags;
  400. *has_video = (flags & OBS_OUTPUT_VIDEO) != 0;
  401. *has_audio = (flags & OBS_OUTPUT_AUDIO) != 0;
  402. }
  403. bool obs_output_can_begin_data_capture(obs_output_t output, uint32_t flags)
  404. {
  405. bool encoded, has_video, has_audio;
  406. if (!output) return false;
  407. if (output->active) return false;
  408. convert_flags(output, flags, &encoded, &has_video, &has_audio);
  409. return can_begin_data_capture(output, encoded, has_video, has_audio);
  410. }
  411. bool obs_output_begin_data_capture(obs_output_t output, uint32_t flags)
  412. {
  413. bool encoded, has_video, has_audio;
  414. if (!output) return false;
  415. if (output->active) return false;
  416. convert_flags(output, flags, &encoded, &has_video, &has_audio);
  417. if (!can_begin_data_capture(output, encoded, has_video, has_audio))
  418. return false;
  419. hook_data_capture(output, encoded, has_video, has_audio);
  420. output->active = true;
  421. signal_start(output, OBS_OUTPUT_SUCCESS);
  422. return true;
  423. }
  424. void obs_output_end_data_capture(obs_output_t output)
  425. {
  426. bool encoded, has_video, has_audio;
  427. void (*encoded_callback)(void *data, struct encoder_packet *packet);
  428. void *param;
  429. if (!output) return;
  430. if (!output->active) return;
  431. convert_flags(output, 0, &encoded, &has_video, &has_audio);
  432. if (encoded) {
  433. encoded_callback = (has_video && has_audio) ?
  434. interleave_packets : output->info.encoded_packet;
  435. param = (has_video && has_audio) ? output : output->data;
  436. if (has_video)
  437. obs_encoder_stop(output->video_encoder,
  438. encoded_callback, param);
  439. if (has_audio)
  440. obs_encoder_stop(output->audio_encoder,
  441. encoded_callback, param);
  442. } else {
  443. if (has_video)
  444. video_output_disconnect(output->video,
  445. output->info.raw_video,
  446. output->data);
  447. if (has_audio)
  448. audio_output_disconnect(output->audio,
  449. output->info.raw_audio,
  450. output->data);
  451. }
  452. output->active = false;
  453. signal_stop(output);
  454. }
  455. void obs_output_signal_start_fail(obs_output_t output, int code)
  456. {
  457. signal_start(output, code);
  458. }