DecklinkInput.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #include "DecklinkInput.hpp"
  2. #include <util/threading.h>
  3. DeckLinkInput::DeckLinkInput(obs_source_t *source,
  4. DeckLinkDeviceDiscovery *discovery_)
  5. : DecklinkBase(discovery_),
  6. source(source)
  7. {
  8. discovery->AddCallback(DeckLinkInput::DevicesChanged, this);
  9. }
  10. DeckLinkInput::~DeckLinkInput(void)
  11. {
  12. discovery->RemoveCallback(DeckLinkInput::DevicesChanged, this);
  13. Deactivate();
  14. }
  15. void DeckLinkInput::DevicesChanged(void *param, DeckLinkDevice *device,
  16. bool added)
  17. {
  18. DeckLinkInput *decklink = reinterpret_cast<DeckLinkInput *>(param);
  19. std::lock_guard<std::recursive_mutex> lock(decklink->deviceMutex);
  20. obs_source_update_properties(decklink->source);
  21. if (added && !decklink->instance) {
  22. const char *hash;
  23. long long mode;
  24. obs_data_t *settings;
  25. BMDVideoConnection videoConnection;
  26. BMDAudioConnection audioConnection;
  27. settings = obs_source_get_settings(decklink->source);
  28. hash = obs_data_get_string(settings, "device_hash");
  29. videoConnection = (BMDVideoConnection)obs_data_get_int(
  30. settings, "video_connection");
  31. audioConnection = (BMDAudioConnection)obs_data_get_int(
  32. settings, "audio_connection");
  33. mode = obs_data_get_int(settings, "mode_id");
  34. obs_data_release(settings);
  35. if (device->GetHash().compare(hash) == 0) {
  36. if (!decklink->activateRefs)
  37. return;
  38. if (decklink->Activate(device, mode, videoConnection,
  39. audioConnection))
  40. os_atomic_dec_long(&decklink->activateRefs);
  41. }
  42. } else if (!added && decklink->instance) {
  43. if (decklink->instance->GetDevice() == device) {
  44. os_atomic_inc_long(&decklink->activateRefs);
  45. decklink->Deactivate();
  46. }
  47. }
  48. }
  49. bool DeckLinkInput::Activate(DeckLinkDevice *device, long long modeId,
  50. BMDVideoConnection bmdVideoConnection,
  51. BMDAudioConnection bmdAudioConnection)
  52. {
  53. std::lock_guard<std::recursive_mutex> lock(deviceMutex);
  54. DeckLinkDevice *curDevice = GetDevice();
  55. const bool same = device == curDevice;
  56. const bool isActive = instance != nullptr;
  57. if (same) {
  58. if (!isActive)
  59. return false;
  60. if (instance->GetActiveModeId() == modeId &&
  61. instance->GetVideoConnection() == bmdVideoConnection &&
  62. instance->GetAudioConnection() == bmdAudioConnection &&
  63. instance->GetActivePixelFormat() == pixelFormat &&
  64. instance->GetActiveColorSpace() == colorSpace &&
  65. instance->GetActiveColorRange() == colorRange &&
  66. instance->GetActiveChannelFormat() == channelFormat &&
  67. instance->GetActiveSwapState() == swap)
  68. return false;
  69. }
  70. if (isActive)
  71. instance->StopCapture();
  72. isCapturing = false;
  73. if (!same)
  74. instance.Set(new DeckLinkDeviceInstance(this, device));
  75. if (instance == nullptr)
  76. return false;
  77. if (GetDevice() == nullptr) {
  78. LOG(LOG_ERROR,
  79. "Tried to activate an input with nullptr device.");
  80. return false;
  81. }
  82. DeckLinkDeviceMode *mode = GetDevice()->FindInputMode(modeId);
  83. if (mode == nullptr) {
  84. instance = nullptr;
  85. return false;
  86. }
  87. if (!instance->StartCapture(mode, allow10Bit, bmdVideoConnection,
  88. bmdAudioConnection)) {
  89. instance = nullptr;
  90. return false;
  91. }
  92. os_atomic_inc_long(&activateRefs);
  93. SaveSettings();
  94. id = modeId;
  95. isCapturing = true;
  96. return true;
  97. }
  98. void DeckLinkInput::Deactivate(void)
  99. {
  100. std::lock_guard<std::recursive_mutex> lock(deviceMutex);
  101. if (instance)
  102. instance->StopCapture();
  103. isCapturing = false;
  104. instance = nullptr;
  105. os_atomic_dec_long(&activateRefs);
  106. }
  107. bool DeckLinkInput::Capturing(void)
  108. {
  109. return isCapturing;
  110. }
  111. void DeckLinkInput::SaveSettings()
  112. {
  113. if (!instance)
  114. return;
  115. DeckLinkDevice *device = instance->GetDevice();
  116. DeckLinkDeviceMode *mode = instance->GetMode();
  117. obs_data_t *settings = obs_source_get_settings(source);
  118. obs_data_set_string(settings, "device_hash", device->GetHash().c_str());
  119. obs_data_set_string(settings, "device_name",
  120. device->GetDisplayName().c_str());
  121. obs_data_set_int(settings, "mode_id", instance->GetActiveModeId());
  122. obs_data_set_string(settings, "mode_name", mode->GetName().c_str());
  123. obs_data_release(settings);
  124. }
  125. obs_source_t *DeckLinkInput::GetSource(void) const
  126. {
  127. return source;
  128. }