obs-audio.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. /******************************************************************************
  2. Copyright (C) 2015 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 "obs-internal.h"
  16. #include "util/util_uint64.h"
  17. struct ts_info {
  18. uint64_t start;
  19. uint64_t end;
  20. };
  21. #define DEBUG_AUDIO 0
  22. #define MAX_BUFFERING_TICKS 45
  23. static void push_audio_tree(obs_source_t *parent, obs_source_t *source, void *p)
  24. {
  25. struct obs_core_audio *audio = p;
  26. if (da_find(audio->render_order, &source, 0) == DARRAY_INVALID) {
  27. obs_source_t *s = obs_source_get_ref(source);
  28. if (s)
  29. da_push_back(audio->render_order, &s);
  30. }
  31. UNUSED_PARAMETER(parent);
  32. }
  33. static inline size_t convert_time_to_frames(size_t sample_rate, uint64_t t)
  34. {
  35. return (size_t)util_mul_div64(t, sample_rate, 1000000000ULL);
  36. }
  37. static inline void mix_audio(struct audio_output_data *mixes,
  38. obs_source_t *source, size_t channels,
  39. size_t sample_rate, struct ts_info *ts)
  40. {
  41. size_t total_floats = AUDIO_OUTPUT_FRAMES;
  42. size_t start_point = 0;
  43. if (source->audio_ts < ts->start || ts->end <= source->audio_ts)
  44. return;
  45. if (source->audio_ts != ts->start) {
  46. start_point = convert_time_to_frames(
  47. sample_rate, source->audio_ts - ts->start);
  48. if (start_point == AUDIO_OUTPUT_FRAMES)
  49. return;
  50. total_floats -= start_point;
  51. }
  52. for (size_t mix_idx = 0; mix_idx < MAX_AUDIO_MIXES; mix_idx++) {
  53. for (size_t ch = 0; ch < channels; ch++) {
  54. register float *mix = mixes[mix_idx].data[ch];
  55. register float *aud =
  56. source->audio_output_buf[mix_idx][ch];
  57. register float *end;
  58. mix += start_point;
  59. end = aud + total_floats;
  60. while (aud < end)
  61. *(mix++) += *(aud++);
  62. }
  63. }
  64. }
  65. static void ignore_audio(obs_source_t *source, size_t channels,
  66. size_t sample_rate)
  67. {
  68. size_t num_floats = source->audio_input_buf[0].size / sizeof(float);
  69. if (num_floats) {
  70. for (size_t ch = 0; ch < channels; ch++)
  71. circlebuf_pop_front(&source->audio_input_buf[ch], NULL,
  72. source->audio_input_buf[ch].size);
  73. source->last_audio_input_buf_size = 0;
  74. source->audio_ts +=
  75. util_mul_div64(num_floats, 1000000000ULL, sample_rate);
  76. }
  77. }
  78. static bool discard_if_stopped(obs_source_t *source, size_t channels)
  79. {
  80. size_t last_size;
  81. size_t size;
  82. last_size = source->last_audio_input_buf_size;
  83. size = source->audio_input_buf[0].size;
  84. if (!size)
  85. return false;
  86. /* if perpetually pending data, it means the audio has stopped,
  87. * so clear the audio data */
  88. if (last_size == size) {
  89. if (!source->pending_stop) {
  90. source->pending_stop = true;
  91. #if DEBUG_AUDIO == 1
  92. blog(LOG_DEBUG, "doing pending stop trick: '%s'",
  93. source->context.name);
  94. #endif
  95. return false;
  96. }
  97. for (size_t ch = 0; ch < channels; ch++)
  98. circlebuf_pop_front(&source->audio_input_buf[ch], NULL,
  99. source->audio_input_buf[ch].size);
  100. source->pending_stop = false;
  101. source->audio_ts = 0;
  102. source->last_audio_input_buf_size = 0;
  103. #if DEBUG_AUDIO == 1
  104. blog(LOG_DEBUG, "source audio data appears to have "
  105. "stopped, clearing");
  106. #endif
  107. return true;
  108. } else {
  109. source->last_audio_input_buf_size = size;
  110. return false;
  111. }
  112. }
  113. #define MAX_AUDIO_SIZE (AUDIO_OUTPUT_FRAMES * sizeof(float))
  114. static inline void discard_audio(struct obs_core_audio *audio,
  115. obs_source_t *source, size_t channels,
  116. size_t sample_rate, struct ts_info *ts)
  117. {
  118. size_t total_floats = AUDIO_OUTPUT_FRAMES;
  119. size_t size;
  120. #if DEBUG_AUDIO == 1
  121. bool is_audio_source = source->info.output_flags & OBS_SOURCE_AUDIO;
  122. #endif
  123. if (source->info.audio_render) {
  124. source->audio_ts = 0;
  125. return;
  126. }
  127. if (ts->end <= source->audio_ts) {
  128. #if DEBUG_AUDIO == 1
  129. blog(LOG_DEBUG,
  130. "can't discard, source "
  131. "timestamp (%" PRIu64 ") >= "
  132. "end timestamp (%" PRIu64 ")",
  133. source->audio_ts, ts->end);
  134. #endif
  135. return;
  136. }
  137. if (source->audio_ts < (ts->start - 1)) {
  138. if (source->audio_pending &&
  139. source->audio_input_buf[0].size < MAX_AUDIO_SIZE &&
  140. discard_if_stopped(source, channels))
  141. return;
  142. #if DEBUG_AUDIO == 1
  143. if (is_audio_source) {
  144. blog(LOG_DEBUG,
  145. "can't discard, source "
  146. "timestamp (%" PRIu64 ") < "
  147. "start timestamp (%" PRIu64 ")",
  148. source->audio_ts, ts->start);
  149. }
  150. #endif
  151. if (audio->total_buffering_ticks == MAX_BUFFERING_TICKS)
  152. ignore_audio(source, channels, sample_rate);
  153. return;
  154. }
  155. if (source->audio_ts != ts->start &&
  156. source->audio_ts != (ts->start - 1)) {
  157. size_t start_point = convert_time_to_frames(
  158. sample_rate, source->audio_ts - ts->start);
  159. if (start_point == AUDIO_OUTPUT_FRAMES) {
  160. #if DEBUG_AUDIO == 1
  161. if (is_audio_source)
  162. blog(LOG_DEBUG, "can't discard, start point is "
  163. "at audio frame count");
  164. #endif
  165. return;
  166. }
  167. total_floats -= start_point;
  168. }
  169. size = total_floats * sizeof(float);
  170. if (source->audio_input_buf[0].size < size) {
  171. if (discard_if_stopped(source, channels))
  172. return;
  173. #if DEBUG_AUDIO == 1
  174. if (is_audio_source)
  175. blog(LOG_DEBUG, "can't discard, data still pending");
  176. #endif
  177. source->audio_ts = ts->end;
  178. return;
  179. }
  180. for (size_t ch = 0; ch < channels; ch++)
  181. circlebuf_pop_front(&source->audio_input_buf[ch], NULL, size);
  182. source->last_audio_input_buf_size = 0;
  183. #if DEBUG_AUDIO == 1
  184. if (is_audio_source)
  185. blog(LOG_DEBUG, "audio discarded, new ts: %" PRIu64, ts->end);
  186. #endif
  187. source->pending_stop = false;
  188. source->audio_ts = ts->end;
  189. }
  190. static void add_audio_buffering(struct obs_core_audio *audio,
  191. size_t sample_rate, struct ts_info *ts,
  192. uint64_t min_ts, const char *buffering_name)
  193. {
  194. struct ts_info new_ts;
  195. uint64_t offset;
  196. uint64_t frames;
  197. size_t total_ms;
  198. size_t ms;
  199. int ticks;
  200. if (audio->total_buffering_ticks == MAX_BUFFERING_TICKS)
  201. return;
  202. if (!audio->buffering_wait_ticks)
  203. audio->buffered_ts = ts->start;
  204. offset = ts->start - min_ts;
  205. frames = ns_to_audio_frames(sample_rate, offset);
  206. ticks = (int)((frames + AUDIO_OUTPUT_FRAMES - 1) / AUDIO_OUTPUT_FRAMES);
  207. audio->total_buffering_ticks += ticks;
  208. if (audio->total_buffering_ticks >= MAX_BUFFERING_TICKS) {
  209. ticks -= audio->total_buffering_ticks - MAX_BUFFERING_TICKS;
  210. audio->total_buffering_ticks = MAX_BUFFERING_TICKS;
  211. blog(LOG_WARNING, "Max audio buffering reached!");
  212. }
  213. ms = ticks * AUDIO_OUTPUT_FRAMES * 1000 / sample_rate;
  214. total_ms = audio->total_buffering_ticks * AUDIO_OUTPUT_FRAMES * 1000 /
  215. sample_rate;
  216. blog(LOG_INFO,
  217. "adding %d milliseconds of audio buffering, total "
  218. "audio buffering is now %d milliseconds"
  219. " (source: %s)\n",
  220. (int)ms, (int)total_ms, buffering_name);
  221. #if DEBUG_AUDIO == 1
  222. blog(LOG_DEBUG,
  223. "min_ts (%" PRIu64 ") < start timestamp "
  224. "(%" PRIu64 ")",
  225. min_ts, ts->start);
  226. blog(LOG_DEBUG, "old buffered ts: %" PRIu64 "-%" PRIu64, ts->start,
  227. ts->end);
  228. #endif
  229. new_ts.start =
  230. audio->buffered_ts -
  231. audio_frames_to_ns(sample_rate, audio->buffering_wait_ticks *
  232. AUDIO_OUTPUT_FRAMES);
  233. while (ticks--) {
  234. int cur_ticks = ++audio->buffering_wait_ticks;
  235. new_ts.end = new_ts.start;
  236. new_ts.start =
  237. audio->buffered_ts -
  238. audio_frames_to_ns(sample_rate,
  239. cur_ticks * AUDIO_OUTPUT_FRAMES);
  240. #if DEBUG_AUDIO == 1
  241. blog(LOG_DEBUG, "add buffered ts: %" PRIu64 "-%" PRIu64,
  242. new_ts.start, new_ts.end);
  243. #endif
  244. circlebuf_push_front(&audio->buffered_timestamps, &new_ts,
  245. sizeof(new_ts));
  246. }
  247. *ts = new_ts;
  248. }
  249. static bool audio_buffer_insuffient(struct obs_source *source,
  250. size_t sample_rate, uint64_t min_ts)
  251. {
  252. size_t total_floats = AUDIO_OUTPUT_FRAMES;
  253. size_t size;
  254. if (source->info.audio_render || source->audio_pending ||
  255. !source->audio_ts) {
  256. return false;
  257. }
  258. if (source->audio_ts != min_ts && source->audio_ts != (min_ts - 1)) {
  259. size_t start_point = convert_time_to_frames(
  260. sample_rate, source->audio_ts - min_ts);
  261. if (start_point >= AUDIO_OUTPUT_FRAMES)
  262. return false;
  263. total_floats -= start_point;
  264. }
  265. size = total_floats * sizeof(float);
  266. if (source->audio_input_buf[0].size < size) {
  267. source->audio_pending = true;
  268. return true;
  269. }
  270. return false;
  271. }
  272. static inline const char *find_min_ts(struct obs_core_data *data,
  273. uint64_t *min_ts)
  274. {
  275. obs_source_t *buffering_source = NULL;
  276. struct obs_source *source = data->first_audio_source;
  277. while (source) {
  278. if (!source->audio_pending && source->audio_ts &&
  279. source->audio_ts < *min_ts) {
  280. *min_ts = source->audio_ts;
  281. buffering_source = source;
  282. }
  283. source = (struct obs_source *)source->next_audio_source;
  284. }
  285. return buffering_source ? obs_source_get_name(buffering_source) : NULL;
  286. }
  287. static inline bool mark_invalid_sources(struct obs_core_data *data,
  288. size_t sample_rate, uint64_t min_ts)
  289. {
  290. bool recalculate = false;
  291. struct obs_source *source = data->first_audio_source;
  292. while (source) {
  293. recalculate |=
  294. audio_buffer_insuffient(source, sample_rate, min_ts);
  295. source = (struct obs_source *)source->next_audio_source;
  296. }
  297. return recalculate;
  298. }
  299. static inline const char *calc_min_ts(struct obs_core_data *data,
  300. size_t sample_rate, uint64_t *min_ts)
  301. {
  302. const char *buffering_name = find_min_ts(data, min_ts);
  303. if (mark_invalid_sources(data, sample_rate, *min_ts))
  304. buffering_name = find_min_ts(data, min_ts);
  305. return buffering_name;
  306. }
  307. static inline void release_audio_sources(struct obs_core_audio *audio)
  308. {
  309. for (size_t i = 0; i < audio->render_order.num; i++)
  310. obs_source_release(audio->render_order.array[i]);
  311. }
  312. bool audio_callback(void *param, uint64_t start_ts_in, uint64_t end_ts_in,
  313. uint64_t *out_ts, uint32_t mixers,
  314. struct audio_output_data *mixes)
  315. {
  316. struct obs_core_data *data = &obs->data;
  317. struct obs_core_audio *audio = &obs->audio;
  318. struct obs_source *source;
  319. size_t sample_rate = audio_output_get_sample_rate(audio->audio);
  320. size_t channels = audio_output_get_channels(audio->audio);
  321. struct ts_info ts = {start_ts_in, end_ts_in};
  322. size_t audio_size;
  323. uint64_t min_ts;
  324. da_resize(audio->render_order, 0);
  325. da_resize(audio->root_nodes, 0);
  326. circlebuf_push_back(&audio->buffered_timestamps, &ts, sizeof(ts));
  327. circlebuf_peek_front(&audio->buffered_timestamps, &ts, sizeof(ts));
  328. min_ts = ts.start;
  329. audio_size = AUDIO_OUTPUT_FRAMES * sizeof(float);
  330. #if DEBUG_AUDIO == 1
  331. blog(LOG_DEBUG, "ts %llu-%llu", ts.start, ts.end);
  332. #endif
  333. /* ------------------------------------------------ */
  334. /* build audio render order
  335. * NOTE: these are source channels, not audio channels */
  336. for (uint32_t i = 0; i < MAX_CHANNELS; i++) {
  337. obs_source_t *source = obs_get_output_source(i);
  338. if (source) {
  339. obs_source_enum_active_tree(source, push_audio_tree,
  340. audio);
  341. push_audio_tree(NULL, source, audio);
  342. da_push_back(audio->root_nodes, &source);
  343. obs_source_release(source);
  344. }
  345. }
  346. pthread_mutex_lock(&data->audio_sources_mutex);
  347. source = data->first_audio_source;
  348. while (source) {
  349. push_audio_tree(NULL, source, audio);
  350. source = (struct obs_source *)source->next_audio_source;
  351. }
  352. pthread_mutex_unlock(&data->audio_sources_mutex);
  353. /* ------------------------------------------------ */
  354. /* render audio data */
  355. for (size_t i = 0; i < audio->render_order.num; i++) {
  356. obs_source_t *source = audio->render_order.array[i];
  357. obs_source_audio_render(source, mixers, channels, sample_rate,
  358. audio_size);
  359. }
  360. /* ------------------------------------------------ */
  361. /* get minimum audio timestamp */
  362. pthread_mutex_lock(&data->audio_sources_mutex);
  363. const char *buffering_name = calc_min_ts(data, sample_rate, &min_ts);
  364. pthread_mutex_unlock(&data->audio_sources_mutex);
  365. /* ------------------------------------------------ */
  366. /* if a source has gone backward in time, buffer */
  367. if (min_ts < ts.start)
  368. add_audio_buffering(audio, sample_rate, &ts, min_ts,
  369. buffering_name);
  370. /* ------------------------------------------------ */
  371. /* mix audio */
  372. if (!audio->buffering_wait_ticks) {
  373. for (size_t i = 0; i < audio->root_nodes.num; i++) {
  374. obs_source_t *source = audio->root_nodes.array[i];
  375. if (source->audio_pending)
  376. continue;
  377. pthread_mutex_lock(&source->audio_buf_mutex);
  378. if (source->audio_output_buf[0][0] && source->audio_ts)
  379. mix_audio(mixes, source, channels, sample_rate,
  380. &ts);
  381. pthread_mutex_unlock(&source->audio_buf_mutex);
  382. }
  383. }
  384. /* ------------------------------------------------ */
  385. /* discard audio */
  386. pthread_mutex_lock(&data->audio_sources_mutex);
  387. source = data->first_audio_source;
  388. while (source) {
  389. pthread_mutex_lock(&source->audio_buf_mutex);
  390. discard_audio(audio, source, channels, sample_rate, &ts);
  391. pthread_mutex_unlock(&source->audio_buf_mutex);
  392. source = (struct obs_source *)source->next_audio_source;
  393. }
  394. pthread_mutex_unlock(&data->audio_sources_mutex);
  395. /* ------------------------------------------------ */
  396. /* release audio sources */
  397. release_audio_sources(audio);
  398. circlebuf_pop_front(&audio->buffered_timestamps, NULL, sizeof(ts));
  399. *out_ts = ts.start;
  400. if (audio->buffering_wait_ticks) {
  401. audio->buffering_wait_ticks--;
  402. return false;
  403. }
  404. UNUSED_PARAMETER(param);
  405. return true;
  406. }