fix QuickSync final
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
|
"log"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -129,6 +130,8 @@ func probeDesktopEncoderCapabilities(ctx context.Context, display int, bounds im
|
|||||||
fpsOptions := []int{240, 165, 144, 120, 90, 60, 30}
|
fpsOptions := []int{240, 165, 144, 120, 90, 60, 30}
|
||||||
sizes := desktopProbeSizes(nativeWidth, nativeHeight)
|
sizes := desktopProbeSizes(nativeWidth, nativeHeight)
|
||||||
providersByProfile := make(map[string][]string)
|
providersByProfile := make(map[string][]string)
|
||||||
|
lastProbeErrors := make(map[string]string)
|
||||||
|
successfulProbes := make(map[string]bool)
|
||||||
probeLoop:
|
probeLoop:
|
||||||
for _, size := range sizes {
|
for _, size := range sizes {
|
||||||
for _, probe := range probes {
|
for _, probe := range probes {
|
||||||
@@ -150,8 +153,12 @@ probeLoop:
|
|||||||
frameBudget := time.Second / time.Duration(fps)
|
frameBudget := time.Second / time.Duration(fps)
|
||||||
if err == nil && averageEncode <= frameBudget+frameBudget/5 {
|
if err == nil && averageEncode <= frameBudget+frameBudget/5 {
|
||||||
maxFPS = fps
|
maxFPS = fps
|
||||||
|
successfulProbes[probe.name] = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
lastProbeErrors[probe.name] = err.Error()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if maxFPS == 0 {
|
if maxFPS == 0 {
|
||||||
continue
|
continue
|
||||||
@@ -165,6 +172,11 @@ probeLoop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
hardwareProfilesFound := len(providersByProfile) > 0
|
hardwareProfilesFound := len(providersByProfile) > 0
|
||||||
|
for provider, probeErr := range lastProbeErrors {
|
||||||
|
if !successfulProbes[provider] {
|
||||||
|
log.Printf("capture: desktop encoder capability probe provider=%s unavailable: %s", provider, probeErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, safe := range safeDesktopProfiles(nativeWidth, nativeHeight) {
|
for _, safe := range safeDesktopProfiles(nativeWidth, nativeHeight) {
|
||||||
key := desktopProfileKey(safe.Width, safe.Height, safe.FPS)
|
key := desktopProfileKey(safe.Width, safe.Height, safe.FPS)
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
#include "bridge_windows.h"
|
#include "bridge_windows.h"
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <d3d10.h>
|
||||||
#include <d3d11.h>
|
#include <d3d11.h>
|
||||||
|
#include <dxgi.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@@ -111,6 +113,34 @@ bool init_session(QSVEncoder* s, std::string& error) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool validate_intel_device(QSVEncoder* s, std::string& error) {
|
||||||
|
IDXGIDevice* dxgiDevice = nullptr;
|
||||||
|
HRESULT hr = s->device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice));
|
||||||
|
if (FAILED(hr)) { error = hr_error("IDXGIDevice", hr); return false; }
|
||||||
|
IDXGIAdapter* adapter = nullptr;
|
||||||
|
hr = dxgiDevice->GetAdapter(&adapter);
|
||||||
|
dxgiDevice->Release();
|
||||||
|
if (FAILED(hr) || !adapter) { error = hr_error("IDXGIDevice::GetAdapter", hr); return false; }
|
||||||
|
DXGI_ADAPTER_DESC desc = {};
|
||||||
|
hr = adapter->GetDesc(&desc);
|
||||||
|
adapter->Release();
|
||||||
|
if (FAILED(hr)) { error = hr_error("IDXGIAdapter::GetDesc", hr); return false; }
|
||||||
|
if (desc.VendorId != 0x8086) {
|
||||||
|
error = "Intel Quick Sync requires the selected display to use an Intel adapter";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool protect_device_context(QSVEncoder* s, std::string& error) {
|
||||||
|
ID3D10Multithread* multithread = nullptr;
|
||||||
|
HRESULT hr = s->context->QueryInterface(__uuidof(ID3D10Multithread), reinterpret_cast<void**>(&multithread));
|
||||||
|
if (FAILED(hr)) { error = hr_error("ID3D10Multithread", hr); return false; }
|
||||||
|
multithread->SetMultithreadProtected(TRUE);
|
||||||
|
multithread->Release();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool init_video_processor(QSVEncoder* s, std::string& error) {
|
bool init_video_processor(QSVEncoder* s, std::string& error) {
|
||||||
HRESULT hr = s->device->QueryInterface(__uuidof(ID3D11VideoDevice), reinterpret_cast<void**>(&s->videoDevice));
|
HRESULT hr = s->device->QueryInterface(__uuidof(ID3D11VideoDevice), reinterpret_cast<void**>(&s->videoDevice));
|
||||||
if (FAILED(hr)) { error = hr_error("ID3D11VideoDevice", hr); return false; }
|
if (FAILED(hr)) { error = hr_error("ID3D11VideoDevice", hr); return false; }
|
||||||
@@ -174,7 +204,9 @@ extern "C" int overlord_qsv_create(void* device, int input_width, int input_heig
|
|||||||
*output = nullptr; auto* s = new QSVEncoder(); std::string error;
|
*output = nullptr; auto* s = new QSVEncoder(); std::string error;
|
||||||
s->device = static_cast<ID3D11Device*>(device); s->device->AddRef(); s->device->GetImmediateContext(&s->context);
|
s->device = static_cast<ID3D11Device*>(device); s->device->AddRef(); s->device->GetImmediateContext(&s->context);
|
||||||
s->inputWidth = input_width; s->inputHeight = input_height; s->width = width; s->height = height;
|
s->inputWidth = input_width; s->inputHeight = input_height; s->width = width; s->height = height;
|
||||||
if (!s->api.open(error) || !init_session(s, error)) goto fail;
|
if (!s->context) { error = "ID3D11Device::GetImmediateContext returned null"; goto fail; }
|
||||||
|
if (!validate_intel_device(s, error) || !protect_device_context(s, error) ||
|
||||||
|
!s->api.open(error) || !init_session(s, error)) goto fail;
|
||||||
{
|
{
|
||||||
mfxStatus sts = s->api.SetHandle(s->session, MFX_HANDLE_D3D11_DEVICE, device);
|
mfxStatus sts = s->api.SetHandle(s->session, MFX_HANDLE_D3D11_DEVICE, device);
|
||||||
if (sts != MFX_ERR_NONE) { error = status_error("MFXVideoCORE_SetHandle", sts); goto fail; }
|
if (sts != MFX_ERR_NONE) { error = status_error("MFXVideoCORE_SetHandle", sts); goto fail; }
|
||||||
@@ -205,7 +237,7 @@ extern "C" int overlord_qsv_encode(overlord_qsv_encoder opaque, void* texture, i
|
|||||||
{
|
{
|
||||||
mfxSurfaceD3D11Tex2D ext = {};
|
mfxSurfaceD3D11Tex2D ext = {};
|
||||||
ext.SurfaceInterface.Header.SurfaceType = MFX_SURFACE_TYPE_D3D11_TEX2D;
|
ext.SurfaceInterface.Header.SurfaceType = MFX_SURFACE_TYPE_D3D11_TEX2D;
|
||||||
ext.SurfaceInterface.Header.SurfaceFlags = MFX_SURFACE_FLAG_IMPORT_SHARED;
|
ext.SurfaceInterface.Header.SurfaceFlags = MFX_SURFACE_FLAG_IMPORT_COPY;
|
||||||
ext.SurfaceInterface.Header.StructSize = sizeof(ext); ext.texture2D = s->nv12;
|
ext.SurfaceInterface.Header.StructSize = sizeof(ext); ext.texture2D = s->nv12;
|
||||||
mfxFrameSurface1* surface = nullptr;
|
mfxFrameSurface1* surface = nullptr;
|
||||||
mfxStatus sts = s->memory->ImportFrameSurface(s->memory, MFX_SURFACE_COMPONENT_ENCODE,
|
mfxStatus sts = s->memory->ImportFrameSurface(s->memory, MFX_SURFACE_COMPONENT_ENCODE,
|
||||||
|
|||||||
@@ -1926,7 +1926,7 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./generated/s
|
|||||||
function ensureDuplicationForH264() {
|
function ensureDuplicationForH264() {
|
||||||
if (!duplicationCtrl || duplicationCtrl.disabled) return;
|
if (!duplicationCtrl || duplicationCtrl.disabled) return;
|
||||||
const isWindows = clientOs.includes("windows") || clientOs.includes("win");
|
const isWindows = clientOs.includes("windows") || clientOs.includes("win");
|
||||||
if (!isWindows || duplicationCtrl.checked) return;
|
if (!isWindows) return;
|
||||||
duplicationCtrl.checked = true;
|
duplicationCtrl.checked = true;
|
||||||
sendCmd("desktop_set_duplication", { enabled: true });
|
sendCmd("desktop_set_duplication", { enabled: true });
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-1
@@ -13,6 +13,22 @@ call bun install
|
|||||||
popd
|
popd
|
||||||
|
|
||||||
echo === Ensuring client dependencies (Go) ===
|
echo === Ensuring client dependencies (Go) ===
|
||||||
|
if not exist "%ROOT%Overlord-Client\third_party\nvcodec\nvEncodeAPI.h" (
|
||||||
|
echo [client] NVIDIA NVENC headers are missing; fetching them...
|
||||||
|
call "%SCRIPT_DIR%vendor-nvcodec-headers.bat"
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo [client] Failed to provision NVIDIA NVENC headers.
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if not exist "%ROOT%Overlord-Client\third_party\amf\include\core\Factory.h" (
|
||||||
|
echo [client] AMD AMF headers are missing; fetching them...
|
||||||
|
call "%SCRIPT_DIR%vendor-amf-headers.bat"
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo [client] Failed to provision AMD AMF headers.
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
)
|
||||||
if not exist "%ROOT%Overlord-Client\third_party\onevpl\include\vpl\mfxdispatcher.h" (
|
if not exist "%ROOT%Overlord-Client\third_party\onevpl\include\vpl\mfxdispatcher.h" (
|
||||||
echo [client] Intel oneVPL headers are missing; fetching them...
|
echo [client] Intel oneVPL headers are missing; fetching them...
|
||||||
call "%SCRIPT_DIR%vendor-onevpl-headers.bat"
|
call "%SCRIPT_DIR%vendor-onevpl-headers.bat"
|
||||||
@@ -39,7 +55,7 @@ set CGO_ENABLED=1
|
|||||||
|
|
||||||
start "Overlord-Server" cmd /k "cd /d ""%ROOT%Overlord-Server"" && set OVERLORD_DISABLE_AGENT_AUTH=true && set OVERLORD_AGENT_TOKEN=dev-token-insecure-local-only && set LOG_LEVEL=debug && set NODE_ENV=development && bun run dev"
|
start "Overlord-Server" cmd /k "cd /d ""%ROOT%Overlord-Server"" && set OVERLORD_DISABLE_AGENT_AUTH=true && set OVERLORD_AGENT_TOKEN=dev-token-insecure-local-only && set LOG_LEVEL=debug && set NODE_ENV=development && bun run dev"
|
||||||
timeout /t 3 /nobreak >nul
|
timeout /t 3 /nobreak >nul
|
||||||
start "Overlord-Client" cmd /k "cd /d ""%ROOT%Overlord-Client"" && set CGO_ENABLED=1 && set OVERLORD_SERVER=wss://localhost:5173 && set OVERLORD_AGENT_TOKEN=dev-token-insecure-local-only && set OVERLORD_TLS_INSECURE_SKIP_VERIFY=true && set OVERLORD_MODE=dev && set OVERLORD_CAPTURE_METRICS=true && set GOINSECURE=* && set GOSUMDB=off && set GOPROXY=https://proxy.golang.org,direct && go mod tidy && go run ./cmd/agent"
|
start "Overlord-Client" cmd /k "cd /d ""%ROOT%Overlord-Client"" && set CGO_ENABLED=1&& set OVERLORD_SERVER=wss://localhost:5173&& set OVERLORD_AGENT_TOKEN=dev-token-insecure-local-only&& set OVERLORD_TLS_INSECURE_SKIP_VERIFY=true&& set OVERLORD_MODE=dev&& set OVERLORD_CAPTURE_METRICS=true&& set GOINSECURE=*&& set GOSUMDB=off&& set GOPROXY=https://proxy.golang.org,direct&& go mod tidy && go run ./cmd/agent"
|
||||||
|
|
||||||
echo Done. Terminals stay open (/k) for logs.
|
echo Done. Terminals stay open (/k) for logs.
|
||||||
endlocal
|
endlocal
|
||||||
|
|||||||
Reference in New Issue
Block a user