mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2026-10-23 16:43:52 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
781b26fd1c | ||
|
|
74173b26eb | ||
|
|
b709bf5402 | ||
|
|
d79536b56d | ||
|
|
74020b537b | ||
|
|
dc92b6d2f3 | ||
|
|
9af0e9f539 | ||
|
|
e4db5c2c18 | ||
|
|
9b8886a6f5 | ||
|
|
f018a71a8a | ||
|
|
b0af84ead1 | ||
|
|
289782c6f3 | ||
|
|
ee557e83c6 | ||
|
|
2bd4b9f721 | ||
|
|
fa6ae80940 | ||
|
|
71c3191e0c | ||
|
|
a614924502 | ||
|
|
a57e947d71 |
No files matched your search
@@ -8,6 +8,8 @@
|
|||||||
<string>Moonlight</string>
|
<string>Moonlight</string>
|
||||||
<key>LSSupportsGameMode</key>
|
<key>LSSupportsGameMode</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>NSApplicationUpdateCycleEnabled</key>
|
||||||
|
<false/>
|
||||||
<key>CFBundleGetInfoString</key>
|
<key>CFBundleGetInfoString</key>
|
||||||
<string>Stream games and other applications from another PC</string>
|
<string>Stream games and other applications from another PC</string>
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ IdentityManager::getSslKey()
|
|||||||
|
|
||||||
BUF_MEM* mem;
|
BUF_MEM* mem;
|
||||||
BIO_get_mem_ptr(bio, &mem);
|
BIO_get_mem_ptr(bio, &mem);
|
||||||
m_CachedSslKey = QSslKey(QByteArray(mem->data, (int)mem->length), QSsl::Rsa);
|
m_CachedSslKey = QSslKey(QByteArray(mem->data, (int)mem->length), getSslCertificate().publicKey().algorithm());
|
||||||
|
|
||||||
BIO_free(bio);
|
BIO_free(bio);
|
||||||
EVP_PKEY_free(pk);
|
EVP_PKEY_free(pk);
|
||||||
|
|||||||
+38
-4
@@ -507,23 +507,47 @@ NvHTTP::openConnection(QUrl baseUrl,
|
|||||||
request.setAttribute(QNetworkRequest::Http2AllowedAttribute, false);
|
request.setAttribute(QNetworkRequest::Http2AllowedAttribute, false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
|
|
||||||
// Use fine-grained idle timeouts to avoid calling QNetworkAccessManager::clearAccessCache(),
|
// Use fine-grained idle timeouts to avoid calling QNetworkAccessManager::clearAccessCache(),
|
||||||
// which tears down the NAM's global thread each time. We must not keep persistent connections
|
// which tears down the NAM's global thread each time. We must not keep persistent connections
|
||||||
// or GFE will puke.
|
// or GFE will puke.
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 12, 0)
|
||||||
|
request.setAttribute(QNetworkRequest::ConnectionCacheExpiryTimeoutSecondsAttribute, -1);
|
||||||
|
#elif QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
|
||||||
request.setAttribute(QNetworkRequest::ConnectionCacheExpiryTimeoutSecondsAttribute, 0);
|
request.setAttribute(QNetworkRequest::ConnectionCacheExpiryTimeoutSecondsAttribute, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto sslErrorsConnection = connect(m_Nam, &QNetworkAccessManager::sslErrors, this, &NvHTTP::handleSslErrors);
|
auto sslErrorsConnection = connect(m_Nam, &QNetworkAccessManager::sslErrors, this, &NvHTTP::handleSslErrors);
|
||||||
QNetworkReply* reply = m_Nam->get(request);
|
QNetworkReply* reply = m_Nam->get(request);
|
||||||
|
|
||||||
// Run the request with a timeout if requested
|
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
|
|
||||||
|
// Connect the quit signals
|
||||||
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||||
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, &loop, &QEventLoop::quit);
|
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, &loop, &QEventLoop::quit);
|
||||||
|
|
||||||
|
// Enforce a transfer timeout if requested
|
||||||
if (timeoutMs) {
|
if (timeoutMs) {
|
||||||
QTimer::singleShot(timeoutMs, &loop, &QEventLoop::quit);
|
QTimer::singleShot(timeoutMs, &loop, &QEventLoop::quit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
|
||||||
|
// Time the request to distinguish a slow response from an unreachable host
|
||||||
|
auto* connectTimer = new QTimer(reply);
|
||||||
|
connectTimer->setSingleShot(true);
|
||||||
|
connect(connectTimer, &QTimer::timeout, reply, [reply, logLevel, url]() {
|
||||||
|
if (!reply->isFinished()) {
|
||||||
|
if (logLevel >= NvLogLevel::NVLL_ERROR) {
|
||||||
|
qWarning() << "Aborting timed out connection for" << url.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
reply->setProperty("timeout_reason", "connection_timeout");
|
||||||
|
reply->abort();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(reply, &QNetworkReply::requestSent, connectTimer, &QTimer::stop);
|
||||||
|
connectTimer->start(REQUEST_TIMEOUT_MS);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (logLevel >= NvLogLevel::NVLL_VERBOSE) {
|
if (logLevel >= NvLogLevel::NVLL_VERBOSE) {
|
||||||
qInfo() << "Executing request:" << url.toString();
|
qInfo() << "Executing request:" << url.toString();
|
||||||
}
|
}
|
||||||
@@ -559,7 +583,11 @@ NvHTTP::openConnection(QUrl baseUrl,
|
|||||||
throw exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
else if (reply->error() == QNetworkReply::OperationCanceledError) {
|
else if (reply->error() == QNetworkReply::OperationCanceledError) {
|
||||||
QtNetworkReplyException exception(QNetworkReply::TimeoutError, "Request timed out");
|
QString reason = reply->property("timeout_reason").toString();
|
||||||
|
QtNetworkReplyException exception(QNetworkReply::TimeoutError,
|
||||||
|
reason == "connection_timeout" ?
|
||||||
|
"Connection timed out" :
|
||||||
|
"Request timed out");
|
||||||
delete reply;
|
delete reply;
|
||||||
throw exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
@@ -570,5 +598,11 @@ NvHTTP::openConnection(QUrl baseUrl,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
|
||||||
|
// The requestSent signal must have stopped the timer for any successful request,
|
||||||
|
// otherwise we could falsely time out a slow response when we connected fine.
|
||||||
|
Q_ASSERT(!connectTimer->isActive());
|
||||||
|
#endif
|
||||||
|
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
@@ -140,6 +140,9 @@ NvPairingManager::getSignatureFromPemCert(const QByteArray& certificate)
|
|||||||
|
|
||||||
X509* cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
|
X509* cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
|
||||||
BIO_free_all(bio);
|
BIO_free_all(bio);
|
||||||
|
if (cert == nullptr) {
|
||||||
|
return QByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray signature = getSignatureFromCert(cert);
|
QByteArray signature = getSignatureFromCert(cert);
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
@@ -159,9 +162,15 @@ NvPairingManager::verifySignature(const QByteArray& data, const QByteArray& sign
|
|||||||
|
|
||||||
X509* cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
|
X509* cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
|
||||||
BIO_free_all(bio);
|
BIO_free_all(bio);
|
||||||
|
if (cert == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
EVP_PKEY* pubKey = X509_get_pubkey(cert);
|
EVP_PKEY* pubKey = X509_get_pubkey(cert);
|
||||||
THROW_BAD_ALLOC_IF_NULL(pubKey);
|
if (pubKey == nullptr) {
|
||||||
|
X509_free(cert);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
EVP_MD_CTX* mdctx = EVP_MD_CTX_create();
|
EVP_MD_CTX* mdctx = EVP_MD_CTX_create();
|
||||||
THROW_BAD_ALLOC_IF_NULL(mdctx);
|
THROW_BAD_ALLOC_IF_NULL(mdctx);
|
||||||
@@ -278,7 +287,7 @@ NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverC
|
|||||||
}
|
}
|
||||||
|
|
||||||
QByteArray challengeResponseData = decrypt(m_Http.getXmlStringFromHex(challengeXml, "challengeresponse"), aesKey);
|
QByteArray challengeResponseData = decrypt(m_Http.getXmlStringFromHex(challengeXml, "challengeresponse"), aesKey);
|
||||||
if (challengeResponseData.size() < hashLength) {
|
if (challengeResponseData.size() < hashLength + 16) {
|
||||||
qCritical() << "Invalid challengeresponse at stage #2";
|
qCritical() << "Invalid challengeresponse at stage #2";
|
||||||
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS);
|
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS);
|
||||||
return PairState::FAILED;
|
return PairState::FAILED;
|
||||||
|
|||||||
+36
-28
@@ -51,7 +51,7 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Display any modal dialogs for configuration warnings
|
// Display any modal dialogs for configuration warnings
|
||||||
if (runConfigChecks) {
|
if (isGuiLaunch) {
|
||||||
if (SystemProperties.isWow64) {
|
if (SystemProperties.isWow64) {
|
||||||
wow64Dialog.open()
|
wow64Dialog.open()
|
||||||
}
|
}
|
||||||
@@ -171,24 +171,28 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
// When we become invisible while streaming is going on,
|
// Polling is only managed from the window for a normal GUI launch;
|
||||||
// stop polling immediately.
|
// CLI commands (stream/quit/pair) manage it via the ComputerSeeker.
|
||||||
if (!visible) {
|
if (isGuiLaunch) {
|
||||||
inactivityTimer.stop()
|
// When we become invisible while streaming is going on,
|
||||||
|
// stop polling immediately.
|
||||||
|
if (!visible) {
|
||||||
|
inactivityTimer.stop()
|
||||||
|
|
||||||
if (pollingActive) {
|
if (pollingActive) {
|
||||||
ComputerManager.stopPollingAsync()
|
ComputerManager.stopPollingAsync()
|
||||||
pollingActive = false
|
pollingActive = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
else if (active) {
|
||||||
else if (active) {
|
// When we become visible and active again, start polling
|
||||||
// When we become visible and active again, start polling
|
inactivityTimer.stop()
|
||||||
inactivityTimer.stop()
|
|
||||||
|
|
||||||
// Restart polling if it was stopped
|
// Restart polling if it was stopped
|
||||||
if (!pollingActive) {
|
if (!pollingActive) {
|
||||||
ComputerManager.startPolling()
|
ComputerManager.startPolling()
|
||||||
pollingActive = true
|
pollingActive = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,20 +201,24 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active) {
|
// Polling is only managed from the window for a normal GUI launch;
|
||||||
// Stop the inactivity timer
|
// CLI commands (stream/quit/pair) manage it via the ComputerSeeker.
|
||||||
inactivityTimer.stop()
|
if (isGuiLaunch) {
|
||||||
|
if (active) {
|
||||||
|
// Stop the inactivity timer
|
||||||
|
inactivityTimer.stop()
|
||||||
|
|
||||||
// Restart polling if it was stopped
|
// Restart polling if it was stopped
|
||||||
if (!pollingActive) {
|
if (!pollingActive) {
|
||||||
ComputerManager.startPolling()
|
ComputerManager.startPolling()
|
||||||
pollingActive = true
|
pollingActive = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Start the inactivity timer to stop polling
|
||||||
|
// if focus does not return within a few minutes.
|
||||||
|
inactivityTimer.restart()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Start the inactivity timer to stop polling
|
|
||||||
// if focus does not return within a few minutes.
|
|
||||||
inactivityTimer.restart()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Poll for gamepad input only when the window is in focus
|
// Poll for gamepad input only when the window is in focus
|
||||||
|
|||||||
+1
-1
@@ -1034,7 +1034,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (hasGUI) {
|
if (hasGUI) {
|
||||||
engine.rootContext()->setContextProperty("initialView", initialView);
|
engine.rootContext()->setContextProperty("initialView", initialView);
|
||||||
engine.rootContext()->setContextProperty("runConfigChecks", commandLineParserResult == GlobalCommandLineParser::NormalStartRequested);
|
engine.rootContext()->setContextProperty("isGuiLaunch", commandLineParserResult == GlobalCommandLineParser::NormalStartRequested);
|
||||||
|
|
||||||
// Load the main.qml file
|
// Load the main.qml file
|
||||||
engine.load(QUrl(QStringLiteral("qrc:/gui/main.qml")));
|
engine.load(QUrl(QStringLiteral("qrc:/gui/main.qml")));
|
||||||
|
|||||||
+37
-23
@@ -1363,34 +1363,48 @@ void Session::getWindowDimensions(int& x, int& y,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the usable display bounds
|
||||||
SDL_Rect usableBounds;
|
SDL_Rect usableBounds;
|
||||||
if (SDL_GetDisplayUsableBounds(displayIndex, &usableBounds) == 0) {
|
if (SDL_GetDisplayUsableBounds(displayIndex, &usableBounds) != 0) {
|
||||||
// If the stream resolution fits within the usable display area, use it directly
|
|
||||||
if (m_StreamConfig.width <= usableBounds.w &&
|
|
||||||
m_StreamConfig.height <= usableBounds.h) {
|
|
||||||
width = m_StreamConfig.width;
|
|
||||||
height = m_StreamConfig.height;
|
|
||||||
} else {
|
|
||||||
// Otherwise, use 80% of usable bounds and preserve aspect ratio
|
|
||||||
SDL_Rect src, dst;
|
|
||||||
src.x = src.y = dst.x = dst.y = 0;
|
|
||||||
src.w = m_StreamConfig.width;
|
|
||||||
src.h = m_StreamConfig.height;
|
|
||||||
|
|
||||||
dst.w = ((int)(usableBounds.w * 0.80f)) & ~0x1; // even width
|
|
||||||
dst.h = ((int)(usableBounds.h * 0.80f)) & ~0x1; // even height
|
|
||||||
|
|
||||||
StreamUtils::scaleSourceToDestinationSurface(&src, &dst);
|
|
||||||
|
|
||||||
width = dst.w;
|
|
||||||
height = dst.h;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"SDL_GetDisplayUsableBounds() failed: %s",
|
"SDL_GetDisplayUsableBounds() failed: %s",
|
||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
|
SDL_zero(usableBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the usable display bounds if they are valid
|
||||||
|
if (usableBounds.w != 0 &&
|
||||||
|
WMUtils::hasDisplayUsableBounds() &&
|
||||||
|
m_StreamConfig.width <= usableBounds.w &&
|
||||||
|
m_StreamConfig.height <= usableBounds.h) {
|
||||||
|
// We fit pixel-perfect in the usable area, so don't scale at all
|
||||||
|
width = m_StreamConfig.width;
|
||||||
|
height = m_StreamConfig.height;
|
||||||
|
}
|
||||||
|
else if (usableBounds.w != 0 || SDL_GetDisplayBounds(displayIndex, &usableBounds) == 0) {
|
||||||
|
// Otherwise, use 80% of usable bounds and preserve aspect ratio
|
||||||
|
SDL_Rect src, dst;
|
||||||
|
src.x = src.y = dst.x = dst.y = 0;
|
||||||
|
src.w = m_StreamConfig.width;
|
||||||
|
src.h = m_StreamConfig.height;
|
||||||
|
|
||||||
|
dst.w = ((int)(usableBounds.w * 0.80f)) & ~0x1; // even width
|
||||||
|
dst.h = ((int)(usableBounds.h * 0.80f)) & ~0x1; // even height
|
||||||
|
|
||||||
|
StreamUtils::scaleSourceToDestinationSurface(&src, &dst);
|
||||||
|
|
||||||
|
// Only scale the size down, never up
|
||||||
|
if (m_StreamConfig.width >= dst.w || m_StreamConfig.height >= dst.h) {
|
||||||
|
width = dst.w;
|
||||||
|
height = dst.h;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
width = m_StreamConfig.width;
|
||||||
|
height = m_StreamConfig.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Oh well, hope for the best
|
||||||
width = m_StreamConfig.width;
|
width = m_StreamConfig.width;
|
||||||
height = m_StreamConfig.height;
|
height = m_StreamConfig.height;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,6 @@
|
|||||||
#include <asm/hwprobe.h>
|
#include <asm/hwprobe.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#else
|
#else
|
||||||
#define __NR_riscv_hwprobe 258
|
|
||||||
struct riscv_hwprobe {
|
struct riscv_hwprobe {
|
||||||
int64_t key;
|
int64_t key;
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
@@ -46,6 +45,10 @@ struct riscv_hwprobe {
|
|||||||
#define RISCV_HWPROBE_KEY_IMA_EXT_0 4
|
#define RISCV_HWPROBE_KEY_IMA_EXT_0 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __NR_riscv_hwprobe
|
||||||
|
#define __NR_riscv_hwprobe 258
|
||||||
|
#endif
|
||||||
|
|
||||||
// RISC-V Scalar AES [E]ncryption and [D]ecryption
|
// RISC-V Scalar AES [E]ncryption and [D]ecryption
|
||||||
#ifndef RISCV_HWPROBE_EXT_ZKND
|
#ifndef RISCV_HWPROBE_EXT_ZKND
|
||||||
#define RISCV_HWPROBE_EXT_ZKND (1 << 11)
|
#define RISCV_HWPROBE_EXT_ZKND (1 << 11)
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ DxVsyncSource::DxVsyncSource(Pacer* pacer) :
|
|||||||
m_LastMonitor(nullptr)
|
m_LastMonitor(nullptr)
|
||||||
{
|
{
|
||||||
SDL_zero(m_WaitForVblankEventParams);
|
SDL_zero(m_WaitForVblankEventParams);
|
||||||
|
m_WaitForVblankEventParams.VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
|
||||||
|
SDL_zero(m_AdapterLuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
DxVsyncSource::~DxVsyncSource()
|
DxVsyncSource::~DxVsyncSource()
|
||||||
@@ -72,41 +74,43 @@ bool DxVsyncSource::isAsync()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DxVsyncSource::waitForVsync()
|
bool DxVsyncSource::waitForVsync()
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
|
||||||
// If the monitor has changed from last time, open the new adapter
|
// If the monitor has changed from last time, open the new adapter
|
||||||
HMONITOR currentMonitor = MonitorFromWindow(m_Window, MONITOR_DEFAULTTONEAREST);
|
HMONITOR currentMonitor = MonitorFromWindow(m_Window, MONITOR_DEFAULTTONEAREST);
|
||||||
if (currentMonitor != m_LastMonitor) {
|
if (!currentMonitor || currentMonitor != m_LastMonitor) {
|
||||||
|
// Close the old adapter
|
||||||
|
if (m_WaitForVblankEventParams.hAdapter != 0) {
|
||||||
|
D3DKMT_CLOSEADAPTER closeAdapterParams = {};
|
||||||
|
closeAdapterParams.hAdapter = m_WaitForVblankEventParams.hAdapter;
|
||||||
|
m_D3DKMTCloseAdapter(&closeAdapterParams);
|
||||||
|
m_WaitForVblankEventParams.hAdapter = 0;
|
||||||
|
}
|
||||||
|
m_LastMonitor = nullptr;
|
||||||
|
|
||||||
|
// We can't wait if we're not on any monitor
|
||||||
|
if (!currentMonitor) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
MONITORINFOEXA monitorInfo = {};
|
MONITORINFOEXA monitorInfo = {};
|
||||||
monitorInfo.cbSize = sizeof(monitorInfo);
|
monitorInfo.cbSize = sizeof(monitorInfo);
|
||||||
if (!GetMonitorInfoA(currentMonitor, &monitorInfo)) {
|
if (!GetMonitorInfoA(currentMonitor, &monitorInfo)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"GetMonitorInfo() failed: %d",
|
"GetMonitorInfo() failed: %d",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVMODEA monitorMode;
|
DEVMODEA monitorMode = {};
|
||||||
monitorMode.dmSize = sizeof(monitorMode);
|
monitorMode.dmSize = sizeof(monitorMode);
|
||||||
if (!EnumDisplaySettingsA(monitorInfo.szDevice, ENUM_CURRENT_SETTINGS, &monitorMode)) {
|
if (!EnumDisplaySettingsA(monitorInfo.szDevice, ENUM_CURRENT_SETTINGS, &monitorMode)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"EnumDisplaySettings() failed: %d",
|
"EnumDisplaySettings() failed: %d",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
return;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Monitor changed: %s %d Hz",
|
|
||||||
monitorInfo.szDevice,
|
|
||||||
monitorMode.dmDisplayFrequency);
|
|
||||||
|
|
||||||
// Close the old adapter
|
|
||||||
if (m_WaitForVblankEventParams.hAdapter != 0) {
|
|
||||||
D3DKMT_CLOSEADAPTER closeAdapterParams = {};
|
|
||||||
closeAdapterParams.hAdapter = m_WaitForVblankEventParams.hAdapter;
|
|
||||||
m_D3DKMTCloseAdapter(&closeAdapterParams);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
D3DKMT_OPENADAPTERFROMHDC openAdapterParams = {};
|
D3DKMT_OPENADAPTERFROMHDC openAdapterParams = {};
|
||||||
@@ -115,7 +119,7 @@ void DxVsyncSource::waitForVsync()
|
|||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"CreateDC() failed: %d",
|
"CreateDC() failed: %d",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open the new adapter
|
// Open the new adapter
|
||||||
@@ -126,21 +130,38 @@ void DxVsyncSource::waitForVsync()
|
|||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"D3DKMTOpenAdapterFromHdc() failed: %x",
|
"D3DKMTOpenAdapterFromHdc() failed: %x",
|
||||||
status);
|
status);
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// VidPnSourceId is scoped to the adapter, so we must also check the adapter LUID
|
||||||
|
if (m_AdapterLuid.LowPart != openAdapterParams.AdapterLuid.LowPart ||
|
||||||
|
m_AdapterLuid.HighPart != openAdapterParams.AdapterLuid.HighPart ||
|
||||||
|
m_WaitForVblankEventParams.VidPnSourceId != openAdapterParams.VidPnSourceId) {
|
||||||
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"Monitor changed: %s %d Hz",
|
||||||
|
monitorInfo.szDevice,
|
||||||
|
monitorMode.dmDisplayFrequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_WaitForVblankEventParams.hAdapter = openAdapterParams.hAdapter;
|
m_WaitForVblankEventParams.hAdapter = openAdapterParams.hAdapter;
|
||||||
m_WaitForVblankEventParams.hDevice = 0;
|
m_WaitForVblankEventParams.hDevice = 0;
|
||||||
m_WaitForVblankEventParams.VidPnSourceId = openAdapterParams.VidPnSourceId;
|
m_WaitForVblankEventParams.VidPnSourceId = openAdapterParams.VidPnSourceId;
|
||||||
|
|
||||||
|
m_AdapterLuid = openAdapterParams.AdapterLuid;
|
||||||
m_LastMonitor = currentMonitor;
|
m_LastMonitor = currentMonitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = m_D3DKMTWaitForVerticalBlankEvent(&m_WaitForVblankEventParams);
|
status = m_D3DKMTWaitForVerticalBlankEvent(&m_WaitForVblankEventParams);
|
||||||
if (status != STATUS_SUCCESS) {
|
if (status != STATUS_SUCCESS) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
if (status != STATUS_GRAPHICS_PRESENT_OCCLUDED) {
|
||||||
"D3DKMTWaitForVerticalBlankEvent() failed: %x",
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
status);
|
"D3DKMTWaitForVerticalBlankEvent() failed: %x",
|
||||||
return;
|
status);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_LastMonitor = nullptr;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@ typedef UINT D3DKMT_HANDLE;
|
|||||||
typedef UINT D3DDDI_VIDEO_PRESENT_SOURCE_ID;
|
typedef UINT D3DDDI_VIDEO_PRESENT_SOURCE_ID;
|
||||||
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
|
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
|
||||||
#define STATUS_GRAPHICS_PRESENT_OCCLUDED ((NTSTATUS)0xC01E0006L)
|
#define STATUS_GRAPHICS_PRESENT_OCCLUDED ((NTSTATUS)0xC01E0006L)
|
||||||
|
#define D3DDDI_ID_UNINITIALIZED (UINT)(~0)
|
||||||
typedef struct _D3DKMT_OPENADAPTERFROMHDC {
|
typedef struct _D3DKMT_OPENADAPTERFROMHDC {
|
||||||
HDC hDc;
|
HDC hDc;
|
||||||
D3DKMT_HANDLE hAdapter;
|
D3DKMT_HANDLE hAdapter;
|
||||||
@@ -39,13 +40,14 @@ public:
|
|||||||
|
|
||||||
virtual bool isAsync() override;
|
virtual bool isAsync() override;
|
||||||
|
|
||||||
virtual void waitForVsync() override;
|
virtual bool waitForVsync() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Pacer* m_Pacer;
|
Pacer* m_Pacer;
|
||||||
HMODULE m_Gdi32Handle;
|
HMODULE m_Gdi32Handle;
|
||||||
HWND m_Window;
|
HWND m_Window;
|
||||||
HMONITOR m_LastMonitor;
|
HMONITOR m_LastMonitor;
|
||||||
|
LUID m_AdapterLuid;
|
||||||
D3DKMT_WAITFORVERTICALBLANKEVENT m_WaitForVblankEventParams;
|
D3DKMT_WAITFORVERTICALBLANKEVENT m_WaitForVblankEventParams;
|
||||||
|
|
||||||
PFND3DKMTOPENADAPTERFROMHDC m_D3DKMTOpenAdapterFromHdc;
|
PFND3DKMTOPENADAPTERFROMHDC m_D3DKMTOpenAdapterFromHdc;
|
||||||
|
|||||||
@@ -115,13 +115,20 @@ int Pacer::vsyncThread(void *context)
|
|||||||
while (!me->m_Stopping) {
|
while (!me->m_Stopping) {
|
||||||
if (async) {
|
if (async) {
|
||||||
// Wait for the VSync source to invoke signalVsync() or 100ms to elapse
|
// Wait for the VSync source to invoke signalVsync() or 100ms to elapse
|
||||||
me->m_FrameQueueLock.lock();
|
QMutexLocker locker(&me->m_FrameQueueLock);
|
||||||
me->m_VsyncSignalled.wait(&me->m_FrameQueueLock, 100);
|
me->m_VsyncSignalled.wait(&me->m_FrameQueueLock, 100);
|
||||||
me->m_FrameQueueLock.unlock();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Let the VSync source wait in the context of our thread
|
// Let the VSync source wait in the context of our thread
|
||||||
me->m_VsyncSource->waitForVsync();
|
if (!me->m_VsyncSource->waitForVsync()) {
|
||||||
|
// Fall back to a fixed delay if the VSync source fails
|
||||||
|
//
|
||||||
|
// NB: We don't actually expect signalVsync() to be called, since
|
||||||
|
// this is a synchronous VSync source, but we wait on m_VsyncSignalled
|
||||||
|
// anyway so that the destructor can immediately wake us on shutdown.
|
||||||
|
QMutexLocker locker(&me->m_FrameQueueLock);
|
||||||
|
me->m_VsyncSignalled.wait(&me->m_FrameQueueLock, 1000 / me->m_DisplayFps);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (me->m_Stopping) {
|
if (me->m_Stopping) {
|
||||||
@@ -148,24 +155,25 @@ int Pacer::renderThread(void* context)
|
|||||||
// Wait for the renderer to be ready for the next frame
|
// Wait for the renderer to be ready for the next frame
|
||||||
me->m_VsyncRenderer->waitToRender();
|
me->m_VsyncRenderer->waitToRender();
|
||||||
|
|
||||||
// Acquire the frame queue lock to protect the queue and
|
AVFrame* frame;
|
||||||
// the not empty condition
|
{
|
||||||
me->m_FrameQueueLock.lock();
|
// Acquire the frame queue lock to protect the queue and
|
||||||
|
// the not empty condition
|
||||||
|
QMutexLocker locker(&me->m_FrameQueueLock);
|
||||||
|
|
||||||
// Wait for a frame to be ready to render
|
// Wait for a frame to be ready to render
|
||||||
while (!me->m_Stopping && me->m_RenderQueue.isEmpty()) {
|
while (!me->m_Stopping && me->m_RenderQueue.isEmpty()) {
|
||||||
me->m_RenderQueueNotEmpty.wait(&me->m_FrameQueueLock);
|
me->m_RenderQueueNotEmpty.wait(&me->m_FrameQueueLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (me->m_Stopping) {
|
||||||
|
// Exit this thread
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame = me->m_RenderQueue.dequeue();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (me->m_Stopping) {
|
|
||||||
// Exit this thread
|
|
||||||
me->m_FrameQueueLock.unlock();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
AVFrame* frame = me->m_RenderQueue.dequeue();
|
|
||||||
me->m_FrameQueueLock.unlock();
|
|
||||||
|
|
||||||
me->renderFrame(frame);
|
me->renderFrame(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +257,7 @@ void Pacer::handleVsync(int timeUntilNextVsyncMillis)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_Stopping) {
|
if (m_Stopping || m_PacingQueue.isEmpty()) {
|
||||||
m_FrameQueueLock.unlock();
|
m_FrameQueueLock.unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -349,7 +357,7 @@ void Pacer::renderFrame(AVFrame* frame)
|
|||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
|
|
||||||
// Drop frames if we have too many queued up for a while
|
// Drop frames if we have too many queued up for a while
|
||||||
m_FrameQueueLock.lock();
|
QMutexLocker frameQueueLocker(&m_FrameQueueLock);
|
||||||
|
|
||||||
int frameDropTarget;
|
int frameDropTarget;
|
||||||
|
|
||||||
@@ -382,13 +390,11 @@ void Pacer::renderFrame(AVFrame* frame)
|
|||||||
AVFrame* frame = m_RenderQueue.dequeue();
|
AVFrame* frame = m_RenderQueue.dequeue();
|
||||||
|
|
||||||
// Drop the lock while we call av_frame_free()
|
// Drop the lock while we call av_frame_free()
|
||||||
m_FrameQueueLock.unlock();
|
frameQueueLocker.unlock();
|
||||||
m_VideoStats->pacerDroppedFrames++;
|
m_VideoStats->pacerDroppedFrames++;
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
m_FrameQueueLock.lock();
|
frameQueueLocker.relock();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_FrameQueueLock.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pacer::dropFrameForEnqueue(QQueue<AVFrame*>& queue)
|
void Pacer::dropFrameForEnqueue(QQueue<AVFrame*>& queue)
|
||||||
|
|||||||
@@ -22,9 +22,10 @@ public:
|
|||||||
// sources require calls to waitForVsync().
|
// sources require calls to waitForVsync().
|
||||||
virtual bool isAsync() = 0;
|
virtual bool isAsync() = 0;
|
||||||
|
|
||||||
virtual void waitForVsync() {
|
virtual bool waitForVsync() {
|
||||||
// Synchronous sources must implement waitForVsync()!
|
// Synchronous sources must implement waitForVsync()!
|
||||||
SDL_assert(false);
|
SDL_assert(false);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace WMUtils {
|
|||||||
bool isRunningWayland();
|
bool isRunningWayland();
|
||||||
bool isRunningWindowManager();
|
bool isRunningWindowManager();
|
||||||
bool isRunningDesktopEnvironment();
|
bool isRunningDesktopEnvironment();
|
||||||
|
bool hasDisplayUsableBounds();
|
||||||
QString getDrmCardOverride();
|
QString getDrmCardOverride();
|
||||||
bool isGpuSlow();
|
bool isGpuSlow();
|
||||||
}
|
}
|
||||||
|
|||||||
+46
@@ -205,6 +205,52 @@ bool WMUtils::isRunningDesktopEnvironment()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WMUtils::hasDisplayUsableBounds()
|
||||||
|
{
|
||||||
|
static SDL_atomic_t hasDisplayUsableBounds;
|
||||||
|
|
||||||
|
// If the value is not set yet, populate it now.
|
||||||
|
int val = SDL_AtomicGet(&hasDisplayUsableBounds);
|
||||||
|
if (!(val & VALUE_SET)) {
|
||||||
|
int numDisplays = SDL_GetNumVideoDisplays();
|
||||||
|
bool hasUsableBounds = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < numDisplays; i++) {
|
||||||
|
SDL_Rect displayBounds;
|
||||||
|
SDL_Rect usableBounds;
|
||||||
|
|
||||||
|
if (SDL_GetDisplayBounds(i, &displayBounds) != 0) {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"SDL_GetDisplayBounds(%d) failed: %s",
|
||||||
|
i, SDL_GetError());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_GetDisplayUsableBounds(i, &usableBounds) != 0) {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"SDL_GetDisplayUsableBounds(%d) failed: %s",
|
||||||
|
i, SDL_GetError());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If at least one display has usable bounds that differ from the
|
||||||
|
// complete bounds, we assume that usable bounds are accurate.
|
||||||
|
if (!SDL_RectEquals(&displayBounds, &usableBounds)) {
|
||||||
|
hasUsableBounds = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate the value to return and have for next time.
|
||||||
|
// This can race with another thread populating the same data,
|
||||||
|
// but that's no big deal.
|
||||||
|
val = VALUE_SET | (hasUsableBounds ? VALUE_TRUE : 0);
|
||||||
|
SDL_AtomicSet(&hasDisplayUsableBounds, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return !!(val & VALUE_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
bool WMUtils::isGpuSlow()
|
bool WMUtils::isGpuSlow()
|
||||||
{
|
{
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|||||||
+25
-3
@@ -1,3 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* h264bitstream - a library for reading and writing H.264 video
|
||||||
|
* Copyright (C) 2005-2007 Auroras Entertainment, LLC
|
||||||
|
* Copyright (C) 2008-2011 Avail-TVN
|
||||||
|
*
|
||||||
|
* Written by Alex Izvorski <aizvorski@gmail.com> and Alex Giladi <alex.giladi@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef _H264_BS_H
|
#ifndef _H264_BS_H
|
||||||
#define _H264_BS_H 1
|
#define _H264_BS_H 1
|
||||||
|
|
||||||
@@ -79,7 +101,7 @@ static inline int bs_eof(bs_t* b) { if (b->p >= b->end) { return 1; } else { ret
|
|||||||
|
|
||||||
static inline int bs_overrun(bs_t* b) { if (b->p > b->end) { return 1; } else { return 0; } }
|
static inline int bs_overrun(bs_t* b) { if (b->p > b->end) { return 1; } else { return 0; } }
|
||||||
|
|
||||||
static inline int bs_pos(bs_t* b) { if (b->p > b->end) { return (b->end - b->start); } else { return (b->p - b->start); } }
|
static inline int bs_pos(bs_t* b) { if (b->p > b->end) { return (int)(b->end - b->start); } else { return (int)(b->p - b->start); } }
|
||||||
|
|
||||||
static inline uint32_t bs_read_u1(bs_t* b)
|
static inline uint32_t bs_read_u1(bs_t* b)
|
||||||
{
|
{
|
||||||
@@ -186,7 +208,7 @@ static inline void bs_write_u(bs_t* b, int n, uint32_t v)
|
|||||||
int i;
|
int i;
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
bs_write_u1(b, (v >> ( n - i - 1 ))&0x01 );
|
bs_write_u1(b, (n - i - 1 >= 32) ? 0 : ((v >> ( n - i - 1 ))&0x01) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,7 +217,7 @@ static inline void bs_write_u8(bs_t* b, uint32_t v)
|
|||||||
#ifdef FAST_U8
|
#ifdef FAST_U8
|
||||||
if (b->bits_left == 8 && ! bs_eof(b)) // can do fast write
|
if (b->bits_left == 8 && ! bs_eof(b)) // can do fast write
|
||||||
{
|
{
|
||||||
b->p[0] = v;
|
b->p[0] = (uint8_t)v;
|
||||||
b->p++;
|
b->p++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* h264bitstream - a library for reading and writing H.264 video
|
||||||
|
* Copyright (C) 2005-2007 Auroras Entertainment, LLC
|
||||||
|
* Copyright (C) 2008-2011 Avail-TVN
|
||||||
|
*
|
||||||
|
* Written by Alex Izvorski <aizvorski@gmail.com> and Alex Giladi <alex.giladi@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* h264bitstream - a library for reading and writing H.264 video
|
||||||
|
* Copyright (C) 2005-2007 Auroras Entertainment, LLC
|
||||||
|
* Copyright (C) 2008-2011 Avail-TVN
|
||||||
|
* Copyright (C) 2012 Alex Izvorski
|
||||||
|
*
|
||||||
|
* Written by Alex Izvorski <aizvorski@gmail.com> and Alex Giladi <alex.giladi@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -361,6 +384,11 @@ void write_seq_parameter_set_rbsp(sps_t* sps, bs_t* b)
|
|||||||
}
|
}
|
||||||
else if( sps->pic_order_cnt_type == 1 )
|
else if( sps->pic_order_cnt_type == 1 )
|
||||||
{
|
{
|
||||||
|
if (sps->num_ref_frames_in_pic_order_cnt_cycle > 256)
|
||||||
|
{
|
||||||
|
sps->num_ref_frames_in_pic_order_cnt_cycle = 256;
|
||||||
|
}
|
||||||
|
|
||||||
bs_write_u1(b, sps->delta_pic_order_always_zero_flag);
|
bs_write_u1(b, sps->delta_pic_order_always_zero_flag);
|
||||||
bs_write_se(b, sps->offset_for_non_ref_pic);
|
bs_write_se(b, sps->offset_for_non_ref_pic);
|
||||||
bs_write_se(b, sps->offset_for_top_to_bottom_field);
|
bs_write_se(b, sps->offset_for_top_to_bottom_field);
|
||||||
@@ -506,6 +534,11 @@ void write_vui_parameters(sps_t* sps, bs_t* b)
|
|||||||
|
|
||||||
void write_hrd_parameters(hrd_t* hrd, bs_t* b)
|
void write_hrd_parameters(hrd_t* hrd, bs_t* b)
|
||||||
{
|
{
|
||||||
|
if (hrd->cpb_cnt_minus1 > 31)
|
||||||
|
{
|
||||||
|
hrd->cpb_cnt_minus1 = 31;
|
||||||
|
}
|
||||||
|
|
||||||
bs_write_ue(b, hrd->cpb_cnt_minus1);
|
bs_write_ue(b, hrd->cpb_cnt_minus1);
|
||||||
bs_write_u(b, 4, hrd->bit_rate_scale);
|
bs_write_u(b, 4, hrd->bit_rate_scale);
|
||||||
bs_write_u(b, 4, hrd->cpb_size_scale);
|
bs_write_u(b, 4, hrd->cpb_size_scale);
|
||||||
|
|||||||
@@ -1,3 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* h264bitstream - a library for reading and writing H.264 video
|
||||||
|
* Copyright (C) 2005-2007 Auroras Entertainment, LLC
|
||||||
|
* Copyright (C) 2008-2011 Avail-TVN
|
||||||
|
*
|
||||||
|
* Written by Alex Izvorski <aizvorski@gmail.com> and Alex Giladi <alex.giladi@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef _H264_STREAM_H
|
#ifndef _H264_STREAM_H
|
||||||
#define _H264_STREAM_H 1
|
#define _H264_STREAM_H 1
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,6 @@ TEMPLATE = lib
|
|||||||
# Build a static library
|
# Build a static library
|
||||||
CONFIG += staticlib
|
CONFIG += staticlib
|
||||||
|
|
||||||
# Disable warnings
|
|
||||||
CONFIG += warn_off
|
|
||||||
|
|
||||||
# Include global qmake defs
|
# Include global qmake defs
|
||||||
include(../globaldefs.pri)
|
include(../globaldefs.pri)
|
||||||
|
|
||||||
|
|||||||
Submodule moonlight-common-c/moonlight-common-c updated: f900dd4767...04053843c9.
@@ -250,7 +250,7 @@ if not x%QT_PATH:\5.=%==x%QT_PATH% (
|
|||||||
set WINDEPLOYQT_ARGS=--no-qmltooling --no-virtualkeyboard
|
set WINDEPLOYQT_ARGS=--no-qmltooling --no-virtualkeyboard
|
||||||
) else (
|
) else (
|
||||||
rem Qt 6.8+
|
rem Qt 6.8+
|
||||||
set WINDEPLOYQT_ARGS=--no-system-d3d-compiler --no-system-dxc-compiler --skip-plugin-types qmltooling,generic --no-ffmpeg
|
set WINDEPLOYQT_ARGS=--no-system-d3d-compiler --no-system-dxc-compiler --skip-plugin-types qmltooling,generic --no-ffmpeg --force-openssl
|
||||||
set WINDEPLOYQT_ARGS=!WINDEPLOYQT_ARGS! --no-quickcontrols2fusion --no-quickcontrols2imagine --no-quickcontrols2universal
|
set WINDEPLOYQT_ARGS=!WINDEPLOYQT_ARGS! --no-quickcontrols2fusion --no-quickcontrols2imagine --no-quickcontrols2universal
|
||||||
set WINDEPLOYQT_ARGS=!WINDEPLOYQT_ARGS! --no-quickcontrols2fusionstyleimpl --no-quickcontrols2imaginestyleimpl --no-quickcontrols2universalstyleimpl --no-quickcontrols2windowsstyleimpl --no-quickcontrols2fluentwinui3styleimpl
|
set WINDEPLOYQT_ARGS=!WINDEPLOYQT_ARGS! --no-quickcontrols2fusionstyleimpl --no-quickcontrols2imaginestyleimpl --no-quickcontrols2universalstyleimpl --no-quickcontrols2windowsstyleimpl --no-quickcontrols2fluentwinui3styleimpl
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in new issue
Block a user