sync-pair-vid.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #include <stdlib.h>
  2. #include <util/threading.h>
  3. #include <util/platform.h>
  4. #include <graphics/graphics.h>
  5. #include <obs.h>
  6. struct sync_pair_vid {
  7. obs_source_t *source;
  8. gs_texture_t *tex;
  9. gs_texture_t *white;
  10. gs_texture_t *black;
  11. };
  12. uint64_t starting_time = 0;
  13. uint64_t last_frame = 0;
  14. static const char *sync_pair_vid_getname(void *unused)
  15. {
  16. UNUSED_PARAMETER(unused);
  17. return "Sync Test Pair (Video)";
  18. }
  19. static void sync_pair_vid_destroy(void *data)
  20. {
  21. struct sync_pair_vid *spv = data;
  22. obs_enter_graphics();
  23. gs_texture_destroy(spv->tex);
  24. gs_texture_destroy(spv->white);
  25. gs_texture_destroy(spv->black);
  26. obs_leave_graphics();
  27. bfree(spv);
  28. }
  29. static inline void fill_texture(uint32_t *pixels, uint32_t pixel)
  30. {
  31. size_t x, y;
  32. for (y = 0; y < 32; y++) {
  33. for (x = 0; x < 32; x++) {
  34. pixels[y * 32 + x] = pixel;
  35. }
  36. }
  37. }
  38. static void *sync_pair_vid_create(obs_data_t *settings, obs_source_t *source)
  39. {
  40. UNUSED_PARAMETER(settings);
  41. struct sync_pair_vid *spv = bzalloc(sizeof(struct sync_pair_vid));
  42. spv->source = source;
  43. obs_enter_graphics();
  44. spv->tex = gs_texture_create(32, 32, GS_RGBA, 1, NULL, GS_DYNAMIC);
  45. spv->white = gs_texture_create(32, 32, GS_RGBA, 1, NULL, GS_DYNAMIC);
  46. spv->black = gs_texture_create(32, 32, GS_RGBA, 1, NULL, GS_DYNAMIC);
  47. uint8_t *ptr;
  48. uint32_t linesize;
  49. if (gs_texture_map(spv->white, &ptr, &linesize)) {
  50. fill_texture((uint32_t *)ptr, 0xFFFFFFFF);
  51. gs_texture_unmap(spv->white);
  52. }
  53. if (gs_texture_map(spv->black, &ptr, &linesize)) {
  54. fill_texture((uint32_t *)ptr, 0xFF000000);
  55. gs_texture_unmap(spv->black);
  56. }
  57. obs_leave_graphics();
  58. return spv;
  59. }
  60. static inline bool whitelist_time(uint64_t ts, uint64_t interval, uint64_t fps_num, uint64_t fps_den)
  61. {
  62. if (!starting_time)
  63. return false;
  64. uint64_t count = (ts - starting_time) / interval;
  65. uint64_t sec = count * fps_den / fps_num;
  66. return sec % 2 == 1;
  67. }
  68. static void sync_pair_vid_render(void *data, gs_effect_t *effect)
  69. {
  70. UNUSED_PARAMETER(effect);
  71. struct sync_pair_vid *spv = data;
  72. uint64_t ts = obs_get_video_frame_time();
  73. if (!starting_time)
  74. starting_time = ts;
  75. uint64_t interval = video_output_get_frame_time(obs_get_video());
  76. const struct video_output_info *voi = video_output_get_info(obs_get_video());
  77. uint64_t fps_num = voi->fps_num;
  78. uint64_t fps_den = voi->fps_den;
  79. bool whitelist = whitelist_time(ts, interval, fps_num, fps_den);
  80. #if 0
  81. if (last_frame != ts) {
  82. uint8_t *ptr;
  83. uint32_t linesize;
  84. if (gs_texture_map(spv->tex, &ptr, &linesize)) {
  85. fill_texture((uint32_t*)ptr, whitelist ? 0xFFFFFFFF : 0xFF000000);
  86. gs_texture_unmap(spv->tex);
  87. }
  88. last_frame = ts;
  89. }
  90. obs_source_draw(spv->tex, 0, 0, 0, 0, 0);
  91. #else
  92. obs_source_draw(whitelist ? spv->white : spv->black, 0, 0, 0, 0, 0);
  93. #endif
  94. }
  95. static uint32_t sync_pair_vid_size(void *data)
  96. {
  97. UNUSED_PARAMETER(data);
  98. return 32;
  99. }
  100. struct obs_source_info sync_video = {
  101. .id = "sync_video",
  102. .type = OBS_SOURCE_TYPE_INPUT,
  103. .output_flags = OBS_SOURCE_VIDEO,
  104. .get_name = sync_pair_vid_getname,
  105. .create = sync_pair_vid_create,
  106. .destroy = sync_pair_vid_destroy,
  107. .video_render = sync_pair_vid_render,
  108. .get_width = sync_pair_vid_size,
  109. .get_height = sync_pair_vid_size,
  110. };