obs-view.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /******************************************************************************
  2. Copyright (C) 2023 by Lain 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. bool obs_view_init(struct obs_view *view)
  17. {
  18. if (!view)
  19. return false;
  20. pthread_mutex_init_value(&view->channels_mutex);
  21. if (pthread_mutex_init(&view->channels_mutex, NULL) != 0) {
  22. blog(LOG_ERROR, "obs_view_init: Failed to create mutex");
  23. return false;
  24. }
  25. return true;
  26. }
  27. obs_view_t *obs_view_create(void)
  28. {
  29. struct obs_view *view = bzalloc(sizeof(struct obs_view));
  30. if (!obs_view_init(view)) {
  31. bfree(view);
  32. view = NULL;
  33. }
  34. return view;
  35. }
  36. void obs_view_free(struct obs_view *view)
  37. {
  38. if (!view)
  39. return;
  40. for (size_t i = 0; i < MAX_CHANNELS; i++) {
  41. struct obs_source *source = view->channels[i];
  42. if (source) {
  43. obs_source_deactivate(source, AUX_VIEW);
  44. obs_source_release(source);
  45. }
  46. }
  47. memset(view->channels, 0, sizeof(view->channels));
  48. pthread_mutex_destroy(&view->channels_mutex);
  49. }
  50. void obs_view_destroy(obs_view_t *view)
  51. {
  52. if (view) {
  53. obs_view_free(view);
  54. bfree(view);
  55. }
  56. }
  57. obs_source_t *obs_view_get_source(obs_view_t *view, uint32_t channel)
  58. {
  59. obs_source_t *source;
  60. assert(channel < MAX_CHANNELS);
  61. if (!view)
  62. return NULL;
  63. if (channel >= MAX_CHANNELS)
  64. return NULL;
  65. pthread_mutex_lock(&view->channels_mutex);
  66. source = obs_source_get_ref(view->channels[channel]);
  67. pthread_mutex_unlock(&view->channels_mutex);
  68. return source;
  69. }
  70. void obs_view_set_source(obs_view_t *view, uint32_t channel, obs_source_t *source)
  71. {
  72. struct obs_source *prev_source;
  73. assert(channel < MAX_CHANNELS);
  74. if (!view)
  75. return;
  76. if (channel >= MAX_CHANNELS)
  77. return;
  78. pthread_mutex_lock(&view->channels_mutex);
  79. source = obs_source_get_ref(source);
  80. prev_source = view->channels[channel];
  81. view->channels[channel] = source;
  82. pthread_mutex_unlock(&view->channels_mutex);
  83. if (source)
  84. obs_source_activate(source, AUX_VIEW);
  85. if (prev_source) {
  86. obs_source_deactivate(prev_source, AUX_VIEW);
  87. obs_source_release(prev_source);
  88. }
  89. }
  90. void obs_view_render(obs_view_t *view)
  91. {
  92. if (!view)
  93. return;
  94. pthread_mutex_lock(&view->channels_mutex);
  95. for (size_t i = 0; i < MAX_CHANNELS; i++) {
  96. struct obs_source *source;
  97. source = view->channels[i];
  98. if (source) {
  99. if (source->removed) {
  100. obs_source_release(source);
  101. view->channels[i] = NULL;
  102. } else {
  103. obs_source_video_render(source);
  104. }
  105. }
  106. }
  107. pthread_mutex_unlock(&view->channels_mutex);
  108. }
  109. static inline size_t find_mix_for_view(obs_view_t *view)
  110. {
  111. for (size_t i = 0, num = obs->video.mixes.num; i < num; i++) {
  112. if (obs->video.mixes.array[i]->view == view)
  113. return i;
  114. }
  115. return DARRAY_INVALID;
  116. }
  117. static inline void set_main_mix()
  118. {
  119. size_t idx = find_mix_for_view(&obs->data.main_view);
  120. struct obs_core_video_mix *mix = NULL;
  121. if (idx != DARRAY_INVALID)
  122. mix = obs->video.mixes.array[idx];
  123. obs->video.main_mix = mix;
  124. }
  125. video_t *obs_view_add(obs_view_t *view)
  126. {
  127. if (!obs->video.main_mix)
  128. return NULL;
  129. return obs_view_add2(view, &obs->video.main_mix->ovi);
  130. }
  131. video_t *obs_view_add2(obs_view_t *view, struct obs_video_info *ovi)
  132. {
  133. if (!view || !ovi)
  134. return NULL;
  135. struct obs_core_video_mix *mix = obs_create_video_mix(ovi);
  136. if (!mix) {
  137. return NULL;
  138. }
  139. mix->view = view;
  140. pthread_mutex_lock(&obs->video.mixes_mutex);
  141. da_push_back(obs->video.mixes, &mix);
  142. set_main_mix();
  143. pthread_mutex_unlock(&obs->video.mixes_mutex);
  144. return mix->video;
  145. }
  146. void obs_view_remove(obs_view_t *view)
  147. {
  148. if (!view)
  149. return;
  150. pthread_mutex_lock(&obs->video.mixes_mutex);
  151. for (size_t i = 0, num = obs->video.mixes.num; i < num; i++) {
  152. if (obs->video.mixes.array[i]->view == view)
  153. obs->video.mixes.array[i]->view = NULL;
  154. }
  155. set_main_mix();
  156. pthread_mutex_unlock(&obs->video.mixes_mutex);
  157. }
  158. bool obs_view_get_video_info(obs_view_t *view, struct obs_video_info *ovi)
  159. {
  160. if (!view)
  161. return false;
  162. pthread_mutex_lock(&obs->video.mixes_mutex);
  163. size_t idx = find_mix_for_view(view);
  164. if (idx != DARRAY_INVALID) {
  165. *ovi = obs->video.mixes.array[idx]->ovi;
  166. pthread_mutex_unlock(&obs->video.mixes_mutex);
  167. return true;
  168. }
  169. pthread_mutex_unlock(&obs->video.mixes_mutex);
  170. return false;
  171. }
  172. void obs_view_enum_video_info(obs_view_t *view, bool (*enum_proc)(void *, struct obs_video_info *), void *param)
  173. {
  174. pthread_mutex_lock(&obs->video.mixes_mutex);
  175. for (size_t i = 0, num = obs->video.mixes.num; i < num; i++) {
  176. struct obs_core_video_mix *mix = obs->video.mixes.array[i];
  177. if (mix->view != view)
  178. continue;
  179. if (!enum_proc(param, &mix->ovi))
  180. break;
  181. }
  182. pthread_mutex_unlock(&obs->video.mixes_mutex);
  183. }