obs.c 5.4 KB

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