diff --git a/plugins/obs-qsv11/QSV_Encoder.cpp b/plugins/obs-qsv11/QSV_Encoder.cpp index dd3a9352e..9d1febc44 100644 --- a/plugins/obs-qsv11/QSV_Encoder.cpp +++ b/plugins/obs-qsv11/QSV_Encoder.cpp @@ -81,11 +81,6 @@ void qsv_encoder_version(unsigned short *major, unsigned short *minor) qsv_t *qsv_encoder_open(qsv_param_t *pParams) { bool false_value = false; - if (!is_active.compare_exchange_strong(false_value, true)) { - do_log(LOG_ERROR, "Cannot have more than one encoder " - "active at a time"); - return NULL; - } QSV_Encoder_Internal *pEncoder = new QSV_Encoder_Internal(impl, ver); mfxStatus sts = pEncoder->Open(pParams); diff --git a/plugins/obs-qsv11/QSV_Encoder_Internal.cpp b/plugins/obs-qsv11/QSV_Encoder_Internal.cpp index a458236ff..5bfdbd0bf 100644 --- a/plugins/obs-qsv11/QSV_Encoder_Internal.cpp +++ b/plugins/obs-qsv11/QSV_Encoder_Internal.cpp @@ -69,6 +69,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__) #define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__) +mfxHDL QSV_Encoder_Internal::g_DX_Handle = NULL; +mfxU16 QSV_Encoder_Internal::g_numEncodersOpen = 0; + QSV_Encoder_Internal::QSV_Encoder_Internal(mfxIMPL& impl, mfxVersion& version) : m_pmfxENC(NULL), m_nSPSBufferSize(100), @@ -152,10 +155,10 @@ mfxStatus QSV_Encoder_Internal::Open(qsv_param_t * pParams) if (m_bUseD3D11) // Use D3D11 surface - sts = Initialize(m_impl, m_ver, &m_session, &m_mfxAllocator, false, false); + sts = Initialize(m_impl, m_ver, &m_session, &m_mfxAllocator, &g_DX_Handle, false, false); else if (m_bD3D9HACK) // Use hack - sts = Initialize(m_impl, m_ver, &m_session, &m_mfxAllocator, false, true); + sts = Initialize(m_impl, m_ver, &m_session, &m_mfxAllocator, &g_DX_Handle, false, true); else sts = Initialize(m_impl, m_ver, &m_session, NULL); @@ -182,6 +185,9 @@ mfxStatus QSV_Encoder_Internal::Open(qsv_param_t * pParams) sts = InitBitstream(); MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + if (sts >= MFX_ERR_NONE) { + g_numEncodersOpen++; + } return sts; } @@ -598,11 +604,15 @@ mfxStatus QSV_Encoder_Internal::ClearData() delete m_pmfxENC; m_pmfxENC = NULL; - if (m_bUseD3D11 || m_bD3D9HACK) + if (sts >= MFX_ERR_NONE) { + g_numEncodersOpen--; + } + + if ((m_bUseD3D11 || m_bD3D9HACK) && (g_numEncodersOpen <= 0)) { Release(); - + g_DX_Handle = NULL; + } m_session.Close(); - return sts; } diff --git a/plugins/obs-qsv11/QSV_Encoder_Internal.h b/plugins/obs-qsv11/QSV_Encoder_Internal.h index def736f28..5e42ec4cd 100644 --- a/plugins/obs-qsv11/QSV_Encoder_Internal.h +++ b/plugins/obs-qsv11/QSV_Encoder_Internal.h @@ -109,5 +109,7 @@ private: bool m_bIsWindows8OrGreater; bool m_bUseD3D11; bool m_bD3D9HACK; + static mfxU16 g_numEncodersOpen; + static mfxHDL g_DX_Handle; // we only want one handle for all instances to use; }; diff --git a/plugins/obs-qsv11/common_utils.h b/plugins/obs-qsv11/common_utils.h index 7a400788a..34f40eed2 100644 --- a/plugins/obs-qsv11/common_utils.h +++ b/plugins/obs-qsv11/common_utils.h @@ -95,7 +95,7 @@ typedef struct { int GetFreeTaskIndex(Task* pTaskPool, mfxU16 nPoolSize); // Initialize Intel Media SDK Session, device/display and memory manager -mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mfxFrameAllocator* pmfxAllocator, bool bCreateSharedHandles = false, bool dx9hack = false); +mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mfxFrameAllocator* pmfxAllocator, mfxHDL *deviceHandle = NULL, bool bCreateSharedHandles = false, bool dx9hack = false); // Release resources (device/display) void Release(); diff --git a/plugins/obs-qsv11/common_utils_windows.cpp b/plugins/obs-qsv11/common_utils_windows.cpp index 29c6b987f..37aedc9e1 100644 --- a/plugins/obs-qsv11/common_utils_windows.cpp +++ b/plugins/obs-qsv11/common_utils_windows.cpp @@ -23,7 +23,7 @@ Copyright(c) 2005-2014 Intel Corporation. All Rights Reserved. * Windows implementation of OS-specific utility functions */ -mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mfxFrameAllocator* pmfxAllocator, bool bCreateSharedHandles, bool dx9hack) +mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mfxFrameAllocator* pmfxAllocator, mfxHDL *deviceHandle, bool bCreateSharedHandles, bool dx9hack) { bCreateSharedHandles; // (Hugh) Currently unused pmfxAllocator; // (Hugh) Currently unused @@ -37,12 +37,15 @@ mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mf MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); // Create DirectX device context - mfxHDL deviceHandle; - sts = CreateHWDevice(*pSession, &deviceHandle, NULL, bCreateSharedHandles); - MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + if (deviceHandle == NULL || *deviceHandle == NULL) { + sts = CreateHWDevice(*pSession, deviceHandle, NULL, bCreateSharedHandles); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + } + + if (deviceHandle == NULL || *deviceHandle == NULL) return MFX_ERR_DEVICE_FAILED; // Provide device manager to Media SDK - sts = pSession->SetHandle(DEVICE_MGR_TYPE, deviceHandle); + sts = pSession->SetHandle(DEVICE_MGR_TYPE, *deviceHandle); MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); pmfxAllocator->pthis = *pSession; // We use Media SDK session ID as the allocation identifier @@ -62,12 +65,14 @@ mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mf MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); // Create DirectX device context - mfxHDL deviceHandle; - sts = DX9_CreateHWDevice(*pSession, &deviceHandle, NULL, bCreateSharedHandles); - MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + if (deviceHandle == NULL || *deviceHandle == NULL ) { + sts = DX9_CreateHWDevice(*pSession, deviceHandle, NULL, false); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + } + if (*deviceHandle == NULL) return MFX_ERR_DEVICE_FAILED; // Provide device manager to Media SDK - sts = pSession->SetHandle(MFX_HANDLE_D3D9_DEVICE_MANAGER, deviceHandle); + sts = pSession->SetHandle(MFX_HANDLE_D3D9_DEVICE_MANAGER, *deviceHandle); MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); pmfxAllocator->pthis = *pSession; // We use Media SDK session ID as the allocation identifier diff --git a/plugins/obs-qsv11/obs-qsv11.c b/plugins/obs-qsv11/obs-qsv11.c index 2ac18ab26..d8c9df5fc 100644 --- a/plugins/obs-qsv11/obs-qsv11.c +++ b/plugins/obs-qsv11/obs-qsv11.c @@ -104,6 +104,7 @@ static int64_t g_pts2dtsShift; static int64_t g_prevDts; static bool g_bFirst; + static const char *obs_qsv_getname(void *type_data) { UNUSED_PARAMETER(type_data); @@ -115,7 +116,10 @@ static void obs_qsv_stop(void *data); static void clear_data(struct obs_qsv *obsqsv) { if (obsqsv->context) { + EnterCriticalSection(&g_QsvCs); qsv_encoder_close(obsqsv->context); + LeaveCriticalSection(&g_QsvCs); + // bfree(obsqsv->sei); bfree(obsqsv->extra_data); @@ -463,7 +467,9 @@ static void *obs_qsv_create(obs_data_t *settings, obs_encoder_t *encoder) obsqsv->encoder = encoder; if (update_settings(obsqsv, settings)) { + EnterCriticalSection(&g_QsvCs); obsqsv->context = qsv_encoder_open(&obsqsv->params); + LeaveCriticalSection(&g_QsvCs); if (obsqsv->context == NULL) warn("qsv failed to load");