DeckLink cap./disp.: check profile for 3D

Verify if active profile is compatible with 3D mode - if not, suggest profile
change.
This commit is contained in:
Martin Pulec
2022-09-21 14:12:14 +02:00
parent a4da8b6b5c
commit 19e8d968bf
4 changed files with 72 additions and 2 deletions

View File

@@ -308,13 +308,27 @@ cleanup:
HRESULT result = cmd;\
if (FAILED(result)) {;\
LOG(LOG_LEVEL_ERROR) << MOD_NAME << name << ": " << bmd_hresult_to_string(result) << "\n";\
ret = false;\
ret = {};\
goto cleanup;\
}\
} while (0)
#define RELEASE_IF_NOT_NULL(x) if (x != nullptr) { x->Release(); x = nullptr; }
static BMDProfileID GetDeckLinkProfileID(IDeckLinkProfile* profile)
{
IDeckLinkProfileAttributes* profileAttributes = nullptr;
if (HRESULT result = profile->QueryInterface(IID_IDeckLinkProfileAttributes, (void**)&profileAttributes); FAILED(result)) {
return {};
}
int64_t profileIDInt = 0;
// Get Profile ID attribute
profileAttributes->GetInt(BMDDeckLinkProfileID, &profileIDInt);
profileAttributes->Release();
return (BMDProfileID) profileIDInt;
}
class ProfileCallback : public IDeckLinkProfileCallback
{
public:
@@ -322,7 +336,7 @@ class ProfileCallback : public IDeckLinkProfileCallback
m_requestedProfile->AddRef();
}
HRESULT ProfileChanging (/* in */ [[maybe_unused]] IDeckLinkProfile* profileToBeActivated, /* in */ [[maybe_unused]] BOOL streamsWillBeForcedToStop) override { return S_OK; }
HRESULT ProfileChanging (/* in */ [[maybe_unused]] IDeckLinkProfile* profileToBeActivated, /* in */ [[maybe_unused]] BMD_BOOL streamsWillBeForcedToStop) override { return S_OK; }
HRESULT ProfileActivated (/* in */ [[maybe_unused]] IDeckLinkProfile* activatedProfile) override {
std::lock_guard<std::mutex> lock(m_profileActivatedMutex);
{
@@ -434,6 +448,50 @@ cleanup:
return ret;
}
static BMDProfileID decklink_get_active_profile_id(IDeckLink *decklink)
{
BMDProfileID ret{};
IDeckLinkProfileManager *manager = nullptr;
if (HRESULT result = decklink->QueryInterface(IID_IDeckLinkProfileManager, (void**)&manager); FAILED(result)) {
if (result != E_NOINTERFACE) {
LOG(LOG_LEVEL_ERROR) << "Cannot get IDeckLinkProfileManager: " << bmd_hresult_to_string(result) << "\n";
}
return {};
}
IDeckLinkProfileIterator *it = nullptr;
IDeckLinkProfile *profile = nullptr;
EXIT_IF_FAILED(manager->GetProfiles(&it), "Cannot get profiles iterator");
while (it->Next(&profile) == S_OK) {
BMD_BOOL isActiveProfile = BMD_FALSE;
if ((profile->IsActive(&isActiveProfile) == S_OK) && isActiveProfile) {
ret = GetDeckLinkProfileID(profile);
profile->Release();
break;
}
profile->Release();
}
cleanup:
RELEASE_IF_NOT_NULL(it);
RELEASE_IF_NOT_NULL(manager);
return ret;
}
bool bmd_check_stereo_profile(IDeckLink *deckLink) {
if (BMDProfileID profile_active = decklink_get_active_profile_id(deckLink)) {
if (profile_active != bmdProfileOneSubDeviceHalfDuplex &&
profile_active != bmdProfileOneSubDeviceFullDuplex) {
uint32_t profile_fcc_host = ntohl(profile_active);
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Active profile '%.4s' may not be compatible with stereo mode.\n", (char *) &profile_fcc_host);
log_msg(LOG_LEVEL_INFO, MOD_NAME "Use 'profile=' parameter to set 1-subdevice mode in either '1dhd' (half) or '1dfd' (full) duplex.\n");
}
return false;
}
return true;
}
string bmd_get_device_name(IDeckLink *decklink) {
BMD_STR deviceNameString = NULL;
char * deviceNameCString = NULL;

View File

@@ -104,6 +104,7 @@ void decklink_uninitialize();
bool blackmagic_api_version_check();
void print_decklink_version(void);
bool bmd_check_stereo_profile(IDeckLink *deckLink);
bool decklink_set_duplex(IDeckLink *decklink, uint32_t profileID);
std::string bmd_get_device_name(IDeckLink *decklink);
std::string bmd_get_audio_connection_name(BMDAudioOutputAnalogAESSwitch audioConnection);

View File

@@ -142,6 +142,7 @@ struct device_state {
bool audio = false; /* wheather we process audio or not */
struct tile *tile = nullptr;
bool init(struct vidcap_decklink_state *s, struct tile *tile, BMDAudioConnection audioConnection);
void check_attributes(struct vidcap_decklink_state *s);
};
struct vidcap_decklink_state {
@@ -1062,6 +1063,13 @@ static bool decklink_cap_configure_audio(struct vidcap_decklink_state *s, unsign
return true;
}
void device_state::check_attributes(struct vidcap_decklink_state *s)
{
if (s->stereo) {
bmd_check_stereo_profile(deckLink);
}
}
#define INIT_ERR() do { RELEASE_IF_NOT_NULL(displayMode); RELEASE_IF_NOT_NULL(displayModeIterator); return false; } while (0)
bool device_state::init(struct vidcap_decklink_state *s, struct tile *t, BMDAudioConnection audioConnection)
{
@@ -1153,6 +1161,8 @@ bool device_state::init(struct vidcap_decklink_state *s, struct tile *t, BMDAudi
BMD_CHECK(deckLinkInput->GetDisplayModeIterator(&displayModeIterator),
"Could not obtain the video input display mode iterator:", INIT_ERR());
check_attributes(s);
int mnum = 0;
#define MODE_SPEC_AUTODETECT -1
#define MODE_SPEC_FOURCC -2

View File

@@ -750,6 +750,7 @@ display_decklink_reconfigure_video(void *state, struct video_desc desc)
}
if (s->stereo) {
bmd_check_stereo_profile(s->state.at(0).deckLink);
if ((int) desc.tile_count != 2) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "In stereo mode exactly "
"2 streams expected, %d received.\n", desc.tile_count);