DecklinkInput.cpp 3.9 KB

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