decklink: Fix automatic pixel format detection
parent
20bb465047
commit
8285141ba5
|
@ -100,7 +100,7 @@ bool DeckLinkInput::Activate(DeckLinkDevice *device, long long modeId,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!instance->StartCapture(mode, bmdVideoConnection,
|
||||
if (!instance->StartCapture(mode, allow10Bit, bmdVideoConnection,
|
||||
bmdAudioConnection)) {
|
||||
instance = nullptr;
|
||||
return false;
|
||||
|
|
|
@ -50,6 +50,7 @@ public:
|
|||
std::string hash;
|
||||
long long id;
|
||||
bool swap = false;
|
||||
bool allow10Bit = false;
|
||||
BMDVideoConnection videoConnection;
|
||||
BMDAudioConnection audioConnection;
|
||||
};
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
#include "OBSVideoFrame.h"
|
||||
|
||||
OBSVideoFrame::OBSVideoFrame(long width, long height)
|
||||
OBSVideoFrame::OBSVideoFrame(long width, long height,
|
||||
BMDPixelFormat pixelFormat)
|
||||
{
|
||||
int bpp = 2;
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->rowBytes = width * 2;
|
||||
this->data = new unsigned char[width * height * 2 + 1];
|
||||
this->rowBytes = width * bpp;
|
||||
this->data = new unsigned char[width * height * bpp + 1];
|
||||
this->pixelFormat = pixelFormat;
|
||||
}
|
||||
|
||||
HRESULT OBSVideoFrame::SetFlags(BMDFrameFlags newFlags)
|
||||
|
|
|
@ -15,7 +15,7 @@ private:
|
|||
unsigned char *data;
|
||||
|
||||
public:
|
||||
OBSVideoFrame(long width, long height);
|
||||
OBSVideoFrame(long width, long height, BMDPixelFormat pixelFormat);
|
||||
|
||||
HRESULT STDMETHODCALLTYPE SetFlags(BMDFrameFlags newFlags) override;
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define AUTO_START "auto_start"
|
||||
#define KEYER "keyer"
|
||||
#define SWAP "swap"
|
||||
#define ALLOW_10_BIT "allow_10_bit"
|
||||
|
||||
#define TEXT_DEVICE obs_module_text("Device")
|
||||
#define TEXT_VIDEO_CONNECTION obs_module_text("VideoConnection")
|
||||
|
@ -39,3 +40,4 @@
|
|||
#define TEXT_ENABLE_KEYER obs_module_text("Keyer")
|
||||
#define TEXT_SWAP obs_module_text("SwapFC-LFE")
|
||||
#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"
|
||||
VideoConnection="Video 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;
|
||||
|
||||
default:
|
||||
case bmdFormat8BitYUV:;
|
||||
case bmdFormat8BitYUV:
|
||||
case bmdFormat10BitYUV:;
|
||||
return VIDEO_FORMAT_UYVY;
|
||||
}
|
||||
|
||||
return VIDEO_FORMAT_UYVY;
|
||||
}
|
||||
|
||||
static inline int ConvertChannelFormat(speaker_layout format)
|
||||
|
@ -168,21 +168,28 @@ void DeckLinkDeviceInstance::HandleVideoFrame(
|
|||
packets->Release();
|
||||
}
|
||||
|
||||
IDeckLinkVideoConversion *frameConverter =
|
||||
CreateVideoConversionInstance();
|
||||
IDeckLinkVideoFrame *frame;
|
||||
if (videoFrame->GetPixelFormat() != convertFrame->GetPixelFormat()) {
|
||||
IDeckLinkVideoConversion *frameConverter =
|
||||
CreateVideoConversionInstance();
|
||||
|
||||
frameConverter->ConvertFrame(videoFrame, convertFrame);
|
||||
frameConverter->ConvertFrame(videoFrame, convertFrame);
|
||||
|
||||
frame = convertFrame;
|
||||
} else {
|
||||
frame = videoFrame;
|
||||
}
|
||||
|
||||
void *bytes;
|
||||
if (convertFrame->GetBytes(&bytes) != S_OK) {
|
||||
if (frame->GetBytes(&bytes) != S_OK) {
|
||||
LOG(LOG_WARNING, "Failed to get video frame data");
|
||||
return;
|
||||
}
|
||||
|
||||
currentFrame.data[0] = (uint8_t *)bytes;
|
||||
currentFrame.linesize[0] = (uint32_t)convertFrame->GetRowBytes();
|
||||
currentFrame.width = (uint32_t)convertFrame->GetWidth();
|
||||
currentFrame.height = (uint32_t)convertFrame->GetHeight();
|
||||
currentFrame.linesize[0] = (uint32_t)frame->GetRowBytes();
|
||||
currentFrame.width = (uint32_t)frame->GetWidth();
|
||||
currentFrame.height = (uint32_t)frame->GetHeight();
|
||||
currentFrame.timestamp = timestamp;
|
||||
|
||||
obs_source_output_video2(
|
||||
|
@ -326,10 +333,22 @@ void DeckLinkDeviceInstance::SetupVideoFormat(DeckLinkDeviceMode *mode_)
|
|||
currentFrame.color_range_min,
|
||||
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
|
||||
LOG(LOG_INFO, "Setup video format: %s, %s, %s",
|
||||
|
@ -340,6 +359,7 @@ void DeckLinkDeviceInstance::SetupVideoFormat(DeckLinkDeviceMode *mode_)
|
|||
}
|
||||
|
||||
bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_,
|
||||
bool allow10Bit_,
|
||||
BMDVideoConnection bmdVideoConnection,
|
||||
BMDAudioConnection bmdAudioConnection)
|
||||
{
|
||||
|
@ -392,7 +412,11 @@ bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_,
|
|||
bool isauto = mode_->GetName() == "Auto";
|
||||
if (isauto) {
|
||||
displayMode = bmdModeNTSC;
|
||||
pixelFormat = bmdFormat10BitYUV;
|
||||
if (allow10Bit) {
|
||||
pixelFormat = bmdFormat10BitYUV;
|
||||
} else {
|
||||
pixelFormat = bmdFormat8BitYUV;
|
||||
}
|
||||
flags = bmdVideoInputEnableFormatDetection;
|
||||
} else {
|
||||
displayMode = mode_->GetDisplayMode();
|
||||
|
@ -401,6 +425,8 @@ bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_,
|
|||
flags = bmdVideoInputFlagDefault;
|
||||
}
|
||||
|
||||
allow10Bit = allow10Bit_;
|
||||
|
||||
const HRESULT videoResult =
|
||||
input->EnableVideoInput(displayMode, pixelFormat, flags);
|
||||
if (videoResult != S_OK) {
|
||||
|
@ -631,15 +657,22 @@ HRESULT STDMETHODCALLTYPE DeckLinkDeviceInstance::VideoInputFormatChanged(
|
|||
{
|
||||
|
||||
if (events & bmdVideoInputColorspaceChanged) {
|
||||
switch (detectedSignalFlags) {
|
||||
case bmdDetectedVideoInputRGB444:
|
||||
if (detectedSignalFlags & bmdDetectedVideoInputRGB444) {
|
||||
pixelFormat = bmdFormat8BitBGRA;
|
||||
break;
|
||||
|
||||
default:
|
||||
case bmdDetectedVideoInputYCbCr422:
|
||||
pixelFormat = bmdFormat10BitYUV;
|
||||
break;
|
||||
}
|
||||
if (detectedSignalFlags & bmdDetectedVideoInputYCbCr422) {
|
||||
if (detectedSignalFlags &
|
||||
bmdDetectedVideoInput10BitDepth) {
|
||||
if (allow10Bit) {
|
||||
pixelFormat = bmdFormat10BitYUV;
|
||||
} else {
|
||||
pixelFormat = bmdFormat8BitYUV;
|
||||
}
|
||||
}
|
||||
if (detectedSignalFlags &
|
||||
bmdDetectedVideoInput8BitDepth) {
|
||||
pixelFormat = bmdFormat8BitYUV;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ protected:
|
|||
AudioRepacker *audioRepacker = nullptr;
|
||||
speaker_layout channelFormat = SPEAKERS_STEREO;
|
||||
bool swap;
|
||||
bool allow10Bit;
|
||||
|
||||
OBSVideoFrame *convertFrame = nullptr;
|
||||
IDeckLinkMutableVideoFrame *decklinkOutputFrame = nullptr;
|
||||
|
@ -85,7 +86,7 @@ public:
|
|||
|
||||
inline DeckLinkDeviceMode *GetMode() const { return mode; }
|
||||
|
||||
bool StartCapture(DeckLinkDeviceMode *mode,
|
||||
bool StartCapture(DeckLinkDeviceMode *mode, bool allow10Bit,
|
||||
BMDVideoConnection bmdVideoConnection,
|
||||
BMDAudioConnection bmdAudioConnection);
|
||||
bool StopCapture(void);
|
||||
|
|
|
@ -80,6 +80,7 @@ static void decklink_update(void *data, obs_data_t *settings)
|
|||
decklink->SetChannelFormat(channelFormat);
|
||||
decklink->hash = std::string(hash);
|
||||
decklink->swap = obs_data_get_bool(settings, SWAP);
|
||||
decklink->allow10Bit = obs_data_get_bool(settings, ALLOW_10_BIT);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -277,6 +281,7 @@ static obs_properties_t *decklink_get_properties(void *data)
|
|||
OBS_COMBO_FORMAT_INT);
|
||||
|
||||
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);
|
||||
|
||||
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, ALLOW_10_BIT, TEXT_ALLOW_10_BIT);
|
||||
|
||||
UNUSED_PARAMETER(data);
|
||||
return props;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue