decklink.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #include "decklink.hpp"
  2. #include "decklink-device-discovery.hpp"
  3. #include "decklink-device-instance.hpp"
  4. #include "decklink-device-mode.hpp"
  5. #include <util/threading.h>
  6. DeckLink::DeckLink(obs_source_t *source, DeckLinkDeviceDiscovery *discovery_) :
  7. discovery(discovery_), source(source)
  8. {
  9. discovery->AddCallback(DeckLink::DevicesChanged, this);
  10. }
  11. DeckLink::~DeckLink(void)
  12. {
  13. discovery->RemoveCallback(DeckLink::DevicesChanged, this);
  14. Deactivate();
  15. }
  16. DeckLinkDevice *DeckLink::GetDevice() const
  17. {
  18. return instance ? instance->GetDevice() : nullptr;
  19. }
  20. void DeckLink::DevicesChanged(void *param, DeckLinkDevice *device, bool added)
  21. {
  22. DeckLink *decklink = reinterpret_cast<DeckLink*>(param);
  23. std::lock_guard<std::recursive_mutex> lock(decklink->deviceMutex);
  24. obs_source_update_properties(decklink->source);
  25. if (added && !decklink->instance) {
  26. const char *hash;
  27. long long mode;
  28. obs_data_t *settings;
  29. settings = obs_source_get_settings(decklink->source);
  30. hash = obs_data_get_string(settings, "device_hash");
  31. mode = obs_data_get_int(settings, "mode_id");
  32. obs_data_release(settings);
  33. if (device->GetHash().compare(hash) == 0) {
  34. if (!decklink->activateRefs)
  35. return;
  36. if (decklink->Activate(device, mode))
  37. os_atomic_dec_long(&decklink->activateRefs);
  38. }
  39. } else if (!added && decklink->instance) {
  40. if (decklink->instance->GetDevice() == device) {
  41. os_atomic_inc_long(&decklink->activateRefs);
  42. decklink->Deactivate();
  43. }
  44. }
  45. }
  46. bool DeckLink::Activate(DeckLinkDevice *device, long long modeId)
  47. {
  48. std::lock_guard<std::recursive_mutex> lock(deviceMutex);
  49. DeckLinkDevice *curDevice = GetDevice();
  50. const bool same = device == curDevice;
  51. const bool isActive = instance != nullptr;
  52. if (same) {
  53. if (!isActive)
  54. return false;
  55. if (instance->GetActiveModeId() == modeId &&
  56. instance->GetActivePixelFormat() == pixelFormat &&
  57. instance->GetActiveColorSpace() == colorSpace &&
  58. instance->GetActiveColorRange() == colorRange &&
  59. instance->GetActiveChannelFormat() == channelFormat)
  60. return false;
  61. }
  62. if (isActive)
  63. instance->StopCapture();
  64. if (!same)
  65. instance.Set(new DeckLinkDeviceInstance(this, device));
  66. if (instance == nullptr)
  67. return false;
  68. DeckLinkDeviceMode *mode = GetDevice()->FindMode(modeId);
  69. if (mode == nullptr) {
  70. instance = nullptr;
  71. return false;
  72. }
  73. if (!instance->StartCapture(mode)) {
  74. instance = nullptr;
  75. return false;
  76. }
  77. os_atomic_inc_long(&activateRefs);
  78. SaveSettings();
  79. return true;
  80. }
  81. void DeckLink::Deactivate(void)
  82. {
  83. std::lock_guard<std::recursive_mutex> lock(deviceMutex);
  84. if (instance)
  85. instance->StopCapture();
  86. instance = nullptr;
  87. os_atomic_dec_long(&activateRefs);
  88. }
  89. void DeckLink::SaveSettings()
  90. {
  91. if (!instance)
  92. return;
  93. DeckLinkDevice *device = instance->GetDevice();
  94. DeckLinkDeviceMode *mode = instance->GetMode();
  95. obs_data_t *settings = obs_source_get_settings(source);
  96. obs_data_set_string(settings, "device_hash",
  97. device->GetHash().c_str());
  98. obs_data_set_string(settings, "device_name",
  99. device->GetDisplayName().c_str());
  100. obs_data_set_int(settings, "mode_id", instance->GetActiveModeId());
  101. obs_data_set_string(settings, "mode_name", mode->GetName().c_str());
  102. obs_data_release(settings);
  103. }
  104. obs_source_t *DeckLink::GetSource(void) const
  105. {
  106. return source;
  107. }