mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-07-14 23:34:08 +00:00
decklink: Output BGRA only when supported
Not all devices support the BGRA pixel format in all video modes. Make sure we fall back to YUV when needed.
This commit is contained in:
parent
7fab3d03e0
commit
ebd5aa9418
|
@ -76,6 +76,21 @@ static inline enum video_format ConvertPixelFormat(BMDPixelFormat format)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int PixelFormatByteSize(BMDPixelFormat format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case bmdFormat8BitBGRA:
|
||||||
|
case bmdFormat8BitARGB:
|
||||||
|
case bmdFormat10BitRGB:
|
||||||
|
case bmdFormat10BitRGBXLE:
|
||||||
|
case bmdFormat10BitRGBX:
|
||||||
|
return 4;
|
||||||
|
default:
|
||||||
|
case bmdFormat8BitYUV:
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline int ConvertChannelFormat(speaker_layout format)
|
static inline int ConvertChannelFormat(speaker_layout format)
|
||||||
{
|
{
|
||||||
switch (format) {
|
switch (format) {
|
||||||
|
@ -604,11 +619,19 @@ bool DeckLinkDeviceInstance::StartOutput(DeckLinkDeviceMode *mode_)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BMDDisplayMode *actualMode = nullptr;
|
||||||
|
decklink_bool_t modeSupportsBGRA = false;
|
||||||
|
output_->DoesSupportVideoMode(
|
||||||
|
bmdVideoConnectionUnspecified, mode_->GetDisplayMode(),
|
||||||
|
bmdFormat8BitBGRA, bmdNoVideoOutputConversion,
|
||||||
|
bmdSupportedVideoModeDefault, actualMode, &modeSupportsBGRA);
|
||||||
|
|
||||||
ComPtr<IDeckLinkKeyer> deckLinkKeyer;
|
ComPtr<IDeckLinkKeyer> deckLinkKeyer;
|
||||||
if (device->GetKeyer(&deckLinkKeyer)) {
|
if (device->GetKeyer(&deckLinkKeyer)) {
|
||||||
const int keyerMode = device->GetKeyerMode();
|
const int keyerMode = device->GetKeyerMode();
|
||||||
if (keyerMode) {
|
if (keyerMode && modeSupportsBGRA) {
|
||||||
deckLinkKeyer->Enable(keyerMode == 1);
|
const bool isExternal = keyerMode == 1;
|
||||||
|
deckLinkKeyer->Enable(isExternal);
|
||||||
deckLinkKeyer->SetLevel(255);
|
deckLinkKeyer->SetLevel(255);
|
||||||
} else {
|
} else {
|
||||||
deckLinkKeyer->Disable();
|
deckLinkKeyer->Disable();
|
||||||
|
@ -618,7 +641,25 @@ bool DeckLinkDeviceInstance::StartOutput(DeckLinkDeviceMode *mode_)
|
||||||
frameQueueDecklinkToObs.reset();
|
frameQueueDecklinkToObs.reset();
|
||||||
frameQueueObsToDecklink.reset();
|
frameQueueObsToDecklink.reset();
|
||||||
|
|
||||||
const int rowSize = decklinkOutput->GetWidth() * 4;
|
struct obs_video_info ovi;
|
||||||
|
const enum video_colorspace colorspace =
|
||||||
|
obs_get_video_info(&ovi) ? ovi.colorspace : VIDEO_CS_DEFAULT;
|
||||||
|
|
||||||
|
const bool source_hdr = (colorspace == VIDEO_CS_2100_PQ) ||
|
||||||
|
(colorspace == VIDEO_CS_2100_HLG);
|
||||||
|
const bool enable_hdr =
|
||||||
|
source_hdr &&
|
||||||
|
(obs_output_get_video_conversion(decklinkOutput->GetOutput())
|
||||||
|
->colorspace == VIDEO_CS_2100_PQ);
|
||||||
|
|
||||||
|
BMDPixelFormat pixelFormat = modeSupportsBGRA ? bmdFormat8BitBGRA
|
||||||
|
: bmdFormat8BitYUV;
|
||||||
|
if (enable_hdr) {
|
||||||
|
pixelFormat = bmdFormat10BitRGBXLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int rowSize =
|
||||||
|
decklinkOutput->GetWidth() * PixelFormatByteSize(pixelFormat);
|
||||||
const int frameSize = rowSize * decklinkOutput->GetHeight();
|
const int frameSize = rowSize * decklinkOutput->GetHeight();
|
||||||
for (std::vector<uint8_t> &blob : frameBlobs) {
|
for (std::vector<uint8_t> &blob : frameBlobs) {
|
||||||
blob.assign(frameSize, 0);
|
blob.assign(frameSize, 0);
|
||||||
|
@ -626,17 +667,6 @@ bool DeckLinkDeviceInstance::StartOutput(DeckLinkDeviceMode *mode_)
|
||||||
}
|
}
|
||||||
activeBlob = nullptr;
|
activeBlob = nullptr;
|
||||||
|
|
||||||
struct obs_video_info ovi;
|
|
||||||
const enum video_colorspace colorspace =
|
|
||||||
obs_get_video_info(&ovi) ? ovi.colorspace : VIDEO_CS_DEFAULT;
|
|
||||||
const bool source_hdr = (colorspace == VIDEO_CS_2100_PQ) ||
|
|
||||||
(colorspace == VIDEO_CS_2100_HLG);
|
|
||||||
const bool enable_hdr =
|
|
||||||
source_hdr &&
|
|
||||||
(obs_output_get_video_conversion(decklinkOutput->GetOutput())
|
|
||||||
->colorspace == VIDEO_CS_2100_PQ);
|
|
||||||
BMDPixelFormat pixelFormat = enable_hdr ? bmdFormat10BitRGBXLE
|
|
||||||
: bmdFormat8BitBGRA;
|
|
||||||
const int64_t minimumPrerollFrames =
|
const int64_t minimumPrerollFrames =
|
||||||
std::max(device->GetMinimumPrerollFrames(), INT64_C(3));
|
std::max(device->GetMinimumPrerollFrames(), INT64_C(3));
|
||||||
for (int64_t i = 0; i < minimumPrerollFrames; ++i) {
|
for (int64_t i = 0; i < minimumPrerollFrames; ++i) {
|
||||||
|
|
|
@ -32,15 +32,30 @@ static void *decklink_output_create(obs_data_t *settings, obs_output_t *output)
|
||||||
DeckLinkDeviceMode *mode =
|
DeckLinkDeviceMode *mode =
|
||||||
device->FindOutputMode(decklinkOutput->modeID);
|
device->FindOutputMode(decklinkOutput->modeID);
|
||||||
|
|
||||||
|
ComPtr<IDeckLinkOutput> output_;
|
||||||
|
device->GetOutput(&output_);
|
||||||
|
|
||||||
|
BMDDisplayMode *actualMode = nullptr;
|
||||||
|
decklink_bool_t modeSupportsBGRA = false;
|
||||||
|
output_->DoesSupportVideoMode(bmdVideoConnectionUnspecified,
|
||||||
|
mode->GetDisplayMode(),
|
||||||
|
bmdFormat8BitBGRA,
|
||||||
|
bmdNoVideoOutputConversion,
|
||||||
|
bmdSupportedVideoModeDefault,
|
||||||
|
actualMode, &modeSupportsBGRA);
|
||||||
|
|
||||||
|
const bool supportsHDR = (device->GetSupportsHDRMetadata() &&
|
||||||
|
!decklinkOutput->force_sdr);
|
||||||
|
|
||||||
struct video_scale_info to = {};
|
struct video_scale_info to = {};
|
||||||
to.format = VIDEO_FORMAT_BGRA;
|
to.format = (modeSupportsBGRA || supportsHDR)
|
||||||
|
? VIDEO_FORMAT_BGRA
|
||||||
|
: VIDEO_FORMAT_UYVY;
|
||||||
to.width = mode->GetWidth();
|
to.width = mode->GetWidth();
|
||||||
to.height = mode->GetHeight();
|
to.height = mode->GetHeight();
|
||||||
to.range = VIDEO_RANGE_FULL;
|
to.range = modeSupportsBGRA ? VIDEO_RANGE_FULL
|
||||||
to.colorspace = (device->GetSupportsHDRMetadata() &&
|
: VIDEO_RANGE_PARTIAL;
|
||||||
!decklinkOutput->force_sdr)
|
to.colorspace = supportsHDR ? VIDEO_CS_2100_PQ : VIDEO_CS_709;
|
||||||
? VIDEO_CS_2100_PQ
|
|
||||||
: VIDEO_CS_709;
|
|
||||||
|
|
||||||
obs_output_set_video_conversion(output, &to);
|
obs_output_set_video_conversion(output, &to);
|
||||||
}
|
}
|
||||||
|
@ -257,9 +272,8 @@ static bool decklink_output_device_changed(obs_properties_t *props,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static obs_properties_t *decklink_output_properties(void *unused)
|
static obs_properties_t *decklink_output_properties(void *)
|
||||||
{
|
{
|
||||||
UNUSED_PARAMETER(unused);
|
|
||||||
obs_properties_t *props = obs_properties_create();
|
obs_properties_t *props = obs_properties_create();
|
||||||
|
|
||||||
obs_property_t *list = obs_properties_add_list(props, DEVICE_HASH,
|
obs_property_t *list = obs_properties_add_list(props, DEVICE_HASH,
|
||||||
|
|
Loading…
Reference in a new issue