obs.c 6.0 KB

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