1
0

obs.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /******************************************************************************
  2. Copyright (C) 2013 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 3 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-data.h"
  16. #include "obs-module.h"
  17. struct obs_data *obs = NULL;
  18. static bool obs_init_graphics(const char *graphics_module,
  19. struct gs_init_data *graphics_data, struct video_info *vi)
  20. {
  21. int errorcode;
  22. bool success = true;
  23. size_t i;
  24. errorcode = gs_create(&obs->graphics, graphics_module, graphics_data);
  25. if (errorcode != GS_SUCCESS) {
  26. if (errorcode == GS_ERROR_MODULENOTFOUND)
  27. blog(LOG_ERROR, "Could not find graphics module '%s'",
  28. graphics_module);
  29. return false;
  30. }
  31. gs_entercontext(obs->graphics);
  32. for (i = 0; i < NUM_TEXTURES; i++) {
  33. obs->copy_surfaces[i] = gs_create_stagesurface(vi->width,
  34. vi->height, graphics_data->format);
  35. if (!obs->copy_surfaces[i])
  36. success = false;
  37. }
  38. if (success) {
  39. obs->default_effect = gs_create_effect_from_file(
  40. "build/data/default.effect", NULL);
  41. if (!obs->default_effect)
  42. success = false;
  43. }
  44. gs_leavecontext();
  45. return success;
  46. }
  47. static bool obs_init_media(struct video_info *vi, struct audio_info *ai)
  48. {
  49. obs->media = media_open();
  50. if (!obs->media)
  51. return false;
  52. if (!obs_reset_video(vi))
  53. return false;
  54. if (!obs_reset_audio(ai))
  55. return false;
  56. return true;
  57. }
  58. static bool obs_init_threading(void)
  59. {
  60. if (pthread_mutex_init(&obs->source_list_mutex, NULL) != 0)
  61. return false;
  62. if (pthread_mutex_init(&obs->display_list_mutex, NULL) != 0)
  63. return false;
  64. if (pthread_create(&obs->video_thread, NULL, obs_video_thread,
  65. obs) != 0)
  66. return false;
  67. obs->thread_initialized = true;
  68. return true;
  69. }
  70. static bool obs_init(const char *graphics_module,
  71. struct gs_init_data *graphics_data,
  72. struct video_info *vi, struct audio_info *ai)
  73. {
  74. obs = bmalloc(sizeof(struct obs_data));
  75. memset(obs, 0, sizeof(struct obs_data));
  76. pthread_mutex_init_value(&obs->source_list_mutex);
  77. pthread_mutex_init_value(&obs->display_list_mutex);
  78. if (!obs_init_graphics(graphics_module, graphics_data, vi))
  79. return false;
  80. if (!obs_init_media(vi, ai))
  81. return false;
  82. if (!obs_init_threading())
  83. return false;
  84. return true;
  85. }
  86. static inline void obs_free_graphics(void)
  87. {
  88. size_t i;
  89. if (!obs->graphics)
  90. return;
  91. gs_entercontext(obs->graphics);
  92. if (obs->copy_mapped)
  93. stagesurface_unmap(obs->copy_surfaces[obs->cur_texture]);
  94. for (i = 0; i < NUM_TEXTURES; i++)
  95. stagesurface_destroy(obs->copy_surfaces[i]);
  96. gs_leavecontext();
  97. gs_destroy(obs->graphics);
  98. }
  99. static inline void obs_free_media(void)
  100. {
  101. video_output_close(obs->video);
  102. audio_output_close(obs->audio);
  103. media_close(obs->media);
  104. }
  105. static inline void obs_free_threading(void)
  106. {
  107. void *thread_ret;
  108. video_output_stop(obs->video);
  109. if (obs->thread_initialized)
  110. pthread_join(obs->video_thread, &thread_ret);
  111. pthread_mutex_destroy(&obs->source_list_mutex);
  112. pthread_mutex_destroy(&obs->display_list_mutex);
  113. }
  114. static void obs_destroy(void)
  115. {
  116. size_t i;
  117. if (!obs)
  118. return;
  119. for (i = 0; i < obs->displays.num; i++)
  120. obs_display_destroy(obs->displays.array[i]);
  121. da_free(obs->input_types);
  122. da_free(obs->filter_types);
  123. da_free(obs->transition_types);
  124. da_free(obs->output_types);
  125. /*da_free(obs->services);*/
  126. da_free(obs->displays);
  127. da_free(obs->sources);
  128. obs_free_threading();
  129. obs_free_media();
  130. obs_free_graphics();
  131. for (i = 0; i < obs->modules.num; i++)
  132. free_module(obs->modules.array+i);
  133. da_free(obs->modules);
  134. bfree(obs);
  135. obs = NULL;
  136. }
  137. bool obs_startup(const char *graphics_module,
  138. struct gs_init_data *graphics_data,
  139. struct video_info *vi, struct audio_info *ai)
  140. {
  141. if (!obs_init(graphics_module, graphics_data, vi, ai)) {
  142. obs_destroy();
  143. return false;
  144. }
  145. return true;
  146. }
  147. void obs_shutdown(void)
  148. {
  149. obs_destroy();
  150. }
  151. bool obs_reset_video(struct video_info *vi)
  152. {
  153. int errorcode;
  154. if (obs->video) {
  155. video_output_close(obs->video);
  156. obs->video = NULL;
  157. }
  158. obs->output_width = vi->width;
  159. obs->output_height = vi->height;
  160. errorcode = video_output_open(&obs->video, obs->media, vi);
  161. if (errorcode == VIDEO_OUTPUT_SUCCESS)
  162. return true;
  163. else if (errorcode == VIDEO_OUTPUT_INVALIDPARAM)
  164. blog(LOG_ERROR, "Invalid video parameters specified");
  165. else
  166. blog(LOG_ERROR, "Could not open video output");
  167. return false;
  168. }
  169. bool obs_reset_audio(struct audio_info *ai)
  170. {
  171. /* TODO */
  172. return true;
  173. }
  174. bool obs_enum_inputs(size_t idx, const char **name)
  175. {
  176. if (idx >= obs->input_types.num)
  177. return false;
  178. *name = obs->input_types.array[idx].name;
  179. return true;
  180. }
  181. bool obs_enum_filters(size_t idx, const char **name)
  182. {
  183. if (idx >= obs->filter_types.num)
  184. return false;
  185. *name = obs->filter_types.array[idx].name;
  186. return true;
  187. }
  188. bool obs_enum_transitions(size_t idx, const char **name)
  189. {
  190. if (idx >= obs->transition_types.num)
  191. return false;
  192. *name = obs->transition_types.array[idx].name;
  193. return true;
  194. }
  195. bool obs_enum_outputs(size_t idx, const char **name)
  196. {
  197. if (idx >= obs->output_types.num)
  198. return false;
  199. *name = obs->output_types.array[idx].name;
  200. return true;
  201. }
  202. graphics_t obs_graphics(void)
  203. {
  204. return obs->graphics;
  205. }
  206. media_t obs_media(void)
  207. {
  208. return obs->media;
  209. }
  210. obs_source_t obs_get_primary_source(void)
  211. {
  212. return obs->primary_source;
  213. }
  214. void obs_set_primary_source(obs_source_t source)
  215. {
  216. obs->primary_source = source;
  217. }