obs.c 5.6 KB

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