2018-09-25 15:51:32 -07:00
|
|
|
#include "DecklinkOutput.hpp"
|
|
|
|
|
|
|
|
#include <util/threading.h>
|
|
|
|
|
2019-06-22 22:13:45 -07:00
|
|
|
DeckLinkOutput::DeckLinkOutput(obs_output_t *output,
|
|
|
|
DeckLinkDeviceDiscovery *discovery_)
|
|
|
|
: DecklinkBase(discovery_), output(output)
|
2018-09-25 15:51:32 -07:00
|
|
|
{
|
|
|
|
discovery->AddCallback(DeckLinkOutput::DevicesChanged, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
DeckLinkOutput::~DeckLinkOutput(void)
|
|
|
|
{
|
|
|
|
discovery->RemoveCallback(DeckLinkOutput::DevicesChanged, this);
|
|
|
|
Deactivate();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeckLinkOutput::DevicesChanged(void *param, DeckLinkDevice *device, bool)
|
|
|
|
{
|
2019-06-22 22:13:45 -07:00
|
|
|
auto *decklink = reinterpret_cast<DeckLinkOutput *>(param);
|
2018-09-25 15:51:32 -07:00
|
|
|
std::lock_guard<std::recursive_mutex> lock(decklink->deviceMutex);
|
|
|
|
|
|
|
|
blog(LOG_DEBUG, "%s", device->GetHash().c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DeckLinkOutput::Activate(DeckLinkDevice *device, long long modeId)
|
|
|
|
{
|
|
|
|
std::lock_guard<std::recursive_mutex> lock(deviceMutex);
|
|
|
|
DeckLinkDevice *curDevice = GetDevice();
|
|
|
|
const bool same = device == curDevice;
|
|
|
|
const bool isActive = instance != nullptr;
|
|
|
|
|
|
|
|
if (same) {
|
|
|
|
if (!isActive)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (instance->GetActiveModeId() == modeId &&
|
2019-06-22 22:13:45 -07:00
|
|
|
instance->GetActivePixelFormat() == pixelFormat &&
|
|
|
|
instance->GetActiveColorSpace() == colorSpace &&
|
|
|
|
instance->GetActiveColorRange() == colorRange &&
|
|
|
|
instance->GetActiveChannelFormat() == channelFormat)
|
2018-09-25 15:51:32 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isActive)
|
|
|
|
instance->StopOutput();
|
|
|
|
|
|
|
|
if (!same)
|
|
|
|
instance.Set(new DeckLinkDeviceInstance(this, device));
|
|
|
|
|
|
|
|
if (instance == nullptr)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
DeckLinkDeviceMode *mode = GetDevice()->FindOutputMode(modeId);
|
|
|
|
if (mode == nullptr) {
|
|
|
|
instance = nullptr;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!instance->StartOutput(mode)) {
|
|
|
|
instance = nullptr;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
os_atomic_inc_long(&activateRefs);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeckLinkOutput::Deactivate(void)
|
|
|
|
{
|
|
|
|
std::lock_guard<std::recursive_mutex> lock(deviceMutex);
|
|
|
|
if (instance)
|
|
|
|
instance->StopOutput();
|
|
|
|
|
|
|
|
instance = nullptr;
|
|
|
|
|
|
|
|
os_atomic_dec_long(&activateRefs);
|
|
|
|
}
|
|
|
|
|
|
|
|
obs_output_t *DeckLinkOutput::GetOutput(void) const
|
|
|
|
{
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeckLinkOutput::DisplayVideoFrame(video_data *frame)
|
|
|
|
{
|
|
|
|
instance->DisplayVideoFrame(frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeckLinkOutput::WriteAudio(audio_data *frames)
|
|
|
|
{
|
|
|
|
instance->WriteAudio(frames);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeckLinkOutput::SetSize(int width, int height)
|
|
|
|
{
|
|
|
|
this->width = width;
|
|
|
|
this->height = height;
|
|
|
|
}
|
|
|
|
|
|
|
|
int DeckLinkOutput::GetWidth()
|
|
|
|
{
|
|
|
|
return width;
|
|
|
|
}
|
|
|
|
|
|
|
|
int DeckLinkOutput::GetHeight()
|
|
|
|
{
|
|
|
|
return height;
|
|
|
|
}
|