decklink: Fix automatic pixel format detection
parent
20bb465047
commit
8285141ba5
|
@ -100,7 +100,7 @@ bool DeckLinkInput::Activate(DeckLinkDevice *device, long long modeId,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!instance->StartCapture(mode, bmdVideoConnection,
|
if (!instance->StartCapture(mode, allow10Bit, bmdVideoConnection,
|
||||||
bmdAudioConnection)) {
|
bmdAudioConnection)) {
|
||||||
instance = nullptr;
|
instance = nullptr;
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -50,6 +50,7 @@ public:
|
||||||
std::string hash;
|
std::string hash;
|
||||||
long long id;
|
long long id;
|
||||||
bool swap = false;
|
bool swap = false;
|
||||||
|
bool allow10Bit = false;
|
||||||
BMDVideoConnection videoConnection;
|
BMDVideoConnection videoConnection;
|
||||||
BMDAudioConnection audioConnection;
|
BMDAudioConnection audioConnection;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
#include "OBSVideoFrame.h"
|
#include "OBSVideoFrame.h"
|
||||||
|
|
||||||
OBSVideoFrame::OBSVideoFrame(long width, long height)
|
OBSVideoFrame::OBSVideoFrame(long width, long height,
|
||||||
|
BMDPixelFormat pixelFormat)
|
||||||
{
|
{
|
||||||
|
int bpp = 2;
|
||||||
this->width = width;
|
this->width = width;
|
||||||
this->height = height;
|
this->height = height;
|
||||||
this->rowBytes = width * 2;
|
this->rowBytes = width * bpp;
|
||||||
this->data = new unsigned char[width * height * 2 + 1];
|
this->data = new unsigned char[width * height * bpp + 1];
|
||||||
|
this->pixelFormat = pixelFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT OBSVideoFrame::SetFlags(BMDFrameFlags newFlags)
|
HRESULT OBSVideoFrame::SetFlags(BMDFrameFlags newFlags)
|
||||||
|
|
|
@ -15,7 +15,7 @@ private:
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OBSVideoFrame(long width, long height);
|
OBSVideoFrame(long width, long height, BMDPixelFormat pixelFormat);
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE SetFlags(BMDFrameFlags newFlags) override;
|
HRESULT STDMETHODCALLTYPE SetFlags(BMDFrameFlags newFlags) override;
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#define AUTO_START "auto_start"
|
#define AUTO_START "auto_start"
|
||||||
#define KEYER "keyer"
|
#define KEYER "keyer"
|
||||||
#define SWAP "swap"
|
#define SWAP "swap"
|
||||||
|
#define ALLOW_10_BIT "allow_10_bit"
|
||||||
|
|
||||||
#define TEXT_DEVICE obs_module_text("Device")
|
#define TEXT_DEVICE obs_module_text("Device")
|
||||||
#define TEXT_VIDEO_CONNECTION obs_module_text("VideoConnection")
|
#define TEXT_VIDEO_CONNECTION obs_module_text("VideoConnection")
|
||||||
|
@ -39,3 +40,4 @@
|
||||||
#define TEXT_ENABLE_KEYER obs_module_text("Keyer")
|
#define TEXT_ENABLE_KEYER obs_module_text("Keyer")
|
||||||
#define TEXT_SWAP obs_module_text("SwapFC-LFE")
|
#define TEXT_SWAP obs_module_text("SwapFC-LFE")
|
||||||
#define TEXT_SWAP_TOOLTIP obs_module_text("SwapFC-LFE.Tooltip")
|
#define TEXT_SWAP_TOOLTIP obs_module_text("SwapFC-LFE.Tooltip")
|
||||||
|
#define TEXT_ALLOW_10_BIT obs_module_text("Allow10Bit")
|
||||||
|
|
|
@ -23,3 +23,4 @@ SwapFC-LFE="Swap FC and LFE"
|
||||||
SwapFC-LFE.Tooltip="Swap Front Center Channel and LFE Channel"
|
SwapFC-LFE.Tooltip="Swap Front Center Channel and LFE Channel"
|
||||||
VideoConnection="Video Connection"
|
VideoConnection="Video Connection"
|
||||||
AudioConnection="Audio Connection"
|
AudioConnection="Audio Connection"
|
||||||
|
Allow10Bit="Allow 10 Bit (Required for SDI captions, may cause performance overhead)"
|
|
@ -24,10 +24,10 @@ static inline enum video_format ConvertPixelFormat(BMDPixelFormat format)
|
||||||
return VIDEO_FORMAT_BGRX;
|
return VIDEO_FORMAT_BGRX;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
case bmdFormat8BitYUV:;
|
case bmdFormat8BitYUV:
|
||||||
}
|
case bmdFormat10BitYUV:;
|
||||||
|
|
||||||
return VIDEO_FORMAT_UYVY;
|
return VIDEO_FORMAT_UYVY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ConvertChannelFormat(speaker_layout format)
|
static inline int ConvertChannelFormat(speaker_layout format)
|
||||||
|
@ -168,21 +168,28 @@ void DeckLinkDeviceInstance::HandleVideoFrame(
|
||||||
packets->Release();
|
packets->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IDeckLinkVideoFrame *frame;
|
||||||
|
if (videoFrame->GetPixelFormat() != convertFrame->GetPixelFormat()) {
|
||||||
IDeckLinkVideoConversion *frameConverter =
|
IDeckLinkVideoConversion *frameConverter =
|
||||||
CreateVideoConversionInstance();
|
CreateVideoConversionInstance();
|
||||||
|
|
||||||
frameConverter->ConvertFrame(videoFrame, convertFrame);
|
frameConverter->ConvertFrame(videoFrame, convertFrame);
|
||||||
|
|
||||||
|
frame = convertFrame;
|
||||||
|
} else {
|
||||||
|
frame = videoFrame;
|
||||||
|
}
|
||||||
|
|
||||||
void *bytes;
|
void *bytes;
|
||||||
if (convertFrame->GetBytes(&bytes) != S_OK) {
|
if (frame->GetBytes(&bytes) != S_OK) {
|
||||||
LOG(LOG_WARNING, "Failed to get video frame data");
|
LOG(LOG_WARNING, "Failed to get video frame data");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentFrame.data[0] = (uint8_t *)bytes;
|
currentFrame.data[0] = (uint8_t *)bytes;
|
||||||
currentFrame.linesize[0] = (uint32_t)convertFrame->GetRowBytes();
|
currentFrame.linesize[0] = (uint32_t)frame->GetRowBytes();
|
||||||
currentFrame.width = (uint32_t)convertFrame->GetWidth();
|
currentFrame.width = (uint32_t)frame->GetWidth();
|
||||||
currentFrame.height = (uint32_t)convertFrame->GetHeight();
|
currentFrame.height = (uint32_t)frame->GetHeight();
|
||||||
currentFrame.timestamp = timestamp;
|
currentFrame.timestamp = timestamp;
|
||||||
|
|
||||||
obs_source_output_video2(
|
obs_source_output_video2(
|
||||||
|
@ -326,10 +333,22 @@ void DeckLinkDeviceInstance::SetupVideoFormat(DeckLinkDeviceMode *mode_)
|
||||||
currentFrame.color_range_min,
|
currentFrame.color_range_min,
|
||||||
currentFrame.color_range_max);
|
currentFrame.color_range_max);
|
||||||
|
|
||||||
if (convertFrame) {
|
|
||||||
delete convertFrame;
|
delete convertFrame;
|
||||||
|
|
||||||
|
BMDPixelFormat convertFormat;
|
||||||
|
switch (pixelFormat) {
|
||||||
|
case bmdFormat8BitBGRA:
|
||||||
|
convertFormat = bmdFormat8BitBGRA;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case bmdFormat10BitYUV:
|
||||||
|
case bmdFormat8BitYUV:;
|
||||||
|
convertFormat = bmdFormat8BitYUV;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
convertFrame = new OBSVideoFrame(mode_->GetWidth(), mode_->GetHeight());
|
|
||||||
|
convertFrame = new OBSVideoFrame(mode_->GetWidth(), mode_->GetHeight(),
|
||||||
|
convertFormat);
|
||||||
|
|
||||||
#ifdef LOG_SETUP_VIDEO_FORMAT
|
#ifdef LOG_SETUP_VIDEO_FORMAT
|
||||||
LOG(LOG_INFO, "Setup video format: %s, %s, %s",
|
LOG(LOG_INFO, "Setup video format: %s, %s, %s",
|
||||||
|
@ -340,6 +359,7 @@ void DeckLinkDeviceInstance::SetupVideoFormat(DeckLinkDeviceMode *mode_)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_,
|
bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_,
|
||||||
|
bool allow10Bit_,
|
||||||
BMDVideoConnection bmdVideoConnection,
|
BMDVideoConnection bmdVideoConnection,
|
||||||
BMDAudioConnection bmdAudioConnection)
|
BMDAudioConnection bmdAudioConnection)
|
||||||
{
|
{
|
||||||
|
@ -392,7 +412,11 @@ bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_,
|
||||||
bool isauto = mode_->GetName() == "Auto";
|
bool isauto = mode_->GetName() == "Auto";
|
||||||
if (isauto) {
|
if (isauto) {
|
||||||
displayMode = bmdModeNTSC;
|
displayMode = bmdModeNTSC;
|
||||||
|
if (allow10Bit) {
|
||||||
pixelFormat = bmdFormat10BitYUV;
|
pixelFormat = bmdFormat10BitYUV;
|
||||||
|
} else {
|
||||||
|
pixelFormat = bmdFormat8BitYUV;
|
||||||
|
}
|
||||||
flags = bmdVideoInputEnableFormatDetection;
|
flags = bmdVideoInputEnableFormatDetection;
|
||||||
} else {
|
} else {
|
||||||
displayMode = mode_->GetDisplayMode();
|
displayMode = mode_->GetDisplayMode();
|
||||||
|
@ -401,6 +425,8 @@ bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_,
|
||||||
flags = bmdVideoInputFlagDefault;
|
flags = bmdVideoInputFlagDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allow10Bit = allow10Bit_;
|
||||||
|
|
||||||
const HRESULT videoResult =
|
const HRESULT videoResult =
|
||||||
input->EnableVideoInput(displayMode, pixelFormat, flags);
|
input->EnableVideoInput(displayMode, pixelFormat, flags);
|
||||||
if (videoResult != S_OK) {
|
if (videoResult != S_OK) {
|
||||||
|
@ -631,15 +657,22 @@ HRESULT STDMETHODCALLTYPE DeckLinkDeviceInstance::VideoInputFormatChanged(
|
||||||
{
|
{
|
||||||
|
|
||||||
if (events & bmdVideoInputColorspaceChanged) {
|
if (events & bmdVideoInputColorspaceChanged) {
|
||||||
switch (detectedSignalFlags) {
|
if (detectedSignalFlags & bmdDetectedVideoInputRGB444) {
|
||||||
case bmdDetectedVideoInputRGB444:
|
|
||||||
pixelFormat = bmdFormat8BitBGRA;
|
pixelFormat = bmdFormat8BitBGRA;
|
||||||
break;
|
}
|
||||||
|
if (detectedSignalFlags & bmdDetectedVideoInputYCbCr422) {
|
||||||
default:
|
if (detectedSignalFlags &
|
||||||
case bmdDetectedVideoInputYCbCr422:
|
bmdDetectedVideoInput10BitDepth) {
|
||||||
|
if (allow10Bit) {
|
||||||
pixelFormat = bmdFormat10BitYUV;
|
pixelFormat = bmdFormat10BitYUV;
|
||||||
break;
|
} else {
|
||||||
|
pixelFormat = bmdFormat8BitYUV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (detectedSignalFlags &
|
||||||
|
bmdDetectedVideoInput8BitDepth) {
|
||||||
|
pixelFormat = bmdFormat8BitYUV;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ protected:
|
||||||
AudioRepacker *audioRepacker = nullptr;
|
AudioRepacker *audioRepacker = nullptr;
|
||||||
speaker_layout channelFormat = SPEAKERS_STEREO;
|
speaker_layout channelFormat = SPEAKERS_STEREO;
|
||||||
bool swap;
|
bool swap;
|
||||||
|
bool allow10Bit;
|
||||||
|
|
||||||
OBSVideoFrame *convertFrame = nullptr;
|
OBSVideoFrame *convertFrame = nullptr;
|
||||||
IDeckLinkMutableVideoFrame *decklinkOutputFrame = nullptr;
|
IDeckLinkMutableVideoFrame *decklinkOutputFrame = nullptr;
|
||||||
|
@ -85,7 +86,7 @@ public:
|
||||||
|
|
||||||
inline DeckLinkDeviceMode *GetMode() const { return mode; }
|
inline DeckLinkDeviceMode *GetMode() const { return mode; }
|
||||||
|
|
||||||
bool StartCapture(DeckLinkDeviceMode *mode,
|
bool StartCapture(DeckLinkDeviceMode *mode, bool allow10Bit,
|
||||||
BMDVideoConnection bmdVideoConnection,
|
BMDVideoConnection bmdVideoConnection,
|
||||||
BMDAudioConnection bmdAudioConnection);
|
BMDAudioConnection bmdAudioConnection);
|
||||||
bool StopCapture(void);
|
bool StopCapture(void);
|
||||||
|
|
|
@ -80,6 +80,7 @@ static void decklink_update(void *data, obs_data_t *settings)
|
||||||
decklink->SetChannelFormat(channelFormat);
|
decklink->SetChannelFormat(channelFormat);
|
||||||
decklink->hash = std::string(hash);
|
decklink->hash = std::string(hash);
|
||||||
decklink->swap = obs_data_get_bool(settings, SWAP);
|
decklink->swap = obs_data_get_bool(settings, SWAP);
|
||||||
|
decklink->allow10Bit = obs_data_get_bool(settings, ALLOW_10_BIT);
|
||||||
decklink->Activate(device, id, videoConnection, audioConnection);
|
decklink->Activate(device, id, videoConnection, audioConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,6 +248,9 @@ static bool mode_id_changed(obs_properties_t *props, obs_property_t *list,
|
||||||
list = obs_properties_get(props, PIXEL_FORMAT);
|
list = obs_properties_get(props, PIXEL_FORMAT);
|
||||||
obs_property_set_visible(list, id != MODE_ID_AUTO);
|
obs_property_set_visible(list, id != MODE_ID_AUTO);
|
||||||
|
|
||||||
|
auto allow10BitProp = obs_properties_get(props, ALLOW_10_BIT);
|
||||||
|
obs_property_set_visible(allow10BitProp, id == MODE_ID_AUTO);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,6 +281,7 @@ static obs_properties_t *decklink_get_properties(void *data)
|
||||||
OBS_COMBO_FORMAT_INT);
|
OBS_COMBO_FORMAT_INT);
|
||||||
|
|
||||||
obs_property_list_add_int(list, "8-bit YUV", bmdFormat8BitYUV);
|
obs_property_list_add_int(list, "8-bit YUV", bmdFormat8BitYUV);
|
||||||
|
obs_property_list_add_int(list, "10-bit YUV", bmdFormat10BitYUV);
|
||||||
obs_property_list_add_int(list, "8-bit BGRA", bmdFormat8BitBGRA);
|
obs_property_list_add_int(list, "8-bit BGRA", bmdFormat8BitBGRA);
|
||||||
|
|
||||||
list = obs_properties_add_list(props, COLOR_SPACE, TEXT_COLOR_SPACE,
|
list = obs_properties_add_list(props, COLOR_SPACE, TEXT_COLOR_SPACE,
|
||||||
|
@ -322,6 +327,8 @@ static obs_properties_t *decklink_get_properties(void *data)
|
||||||
|
|
||||||
obs_properties_add_bool(props, DEACTIVATE_WNS, TEXT_DWNS);
|
obs_properties_add_bool(props, DEACTIVATE_WNS, TEXT_DWNS);
|
||||||
|
|
||||||
|
obs_properties_add_bool(props, ALLOW_10_BIT, TEXT_ALLOW_10_BIT);
|
||||||
|
|
||||||
UNUSED_PARAMETER(data);
|
UNUSED_PARAMETER(data);
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue