obs-qsv: Allow for multiple QSV encoders
Allow multiple QSV encoders, usefull for live + recorded parallel sessions. The first QSV encoder will create a DirectX device and return a handle / pointer. Any additional QSV encoder will use that same pointer to the DirectX device. We keep track of the number of open QSV encoders so that we wait to close the DirectX resources after all encoders are closed. Closes obsproject/obs-studio#1341
This commit is contained in:
committed by
jp9000
parent
8c910a9e3b
commit
3a08e858a6
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
|
@@ -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();
|
||||
|
@@ -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
|
||||
|
@@ -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");
|
||||
|
Reference in New Issue
Block a user