From 9cc20c27abff3fc8c10662ae6c80f2d3f7cccdc1 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 5 Aug 2018 14:55:26 -0700 Subject: [PATCH] Add support for native resolution streaming --- app/gui/SettingsView.qml | 53 +++++++++++++++++++++++---- app/settings/streamingpreferences.cpp | 41 +++++++++++++++++++-- app/settings/streamingpreferences.h | 3 ++ app/streaming/session.cpp | 18 +++++++++ 4 files changed, 104 insertions(+), 11 deletions(-) diff --git a/app/gui/SettingsView.qml b/app/gui/SettingsView.qml index 3ba335cc..ce08b88a 100644 --- a/app/gui/SettingsView.qml +++ b/app/gui/SettingsView.qml @@ -43,7 +43,7 @@ ScrollView { Label { width: parent.width id: resFPSdesc - text: qsTr("Setting values too high for your PC may cause lag, stuttering, or errors") + text: qsTr("Setting values too high for your PC may cause lag, stuttering, or errors.") font.pointSize: 9 wrapMode: Text.Wrap color: "white" @@ -55,6 +55,41 @@ ScrollView { ComboBox { // ignore setting the index at first, and actually set it when the component is loaded Component.onCompleted: { + // Add native resolutions for all attached displays + for (var displayIndex = 0;; displayIndex++) { + var screenRect = prefs.getDisplayResolution(displayIndex) + if (screenRect.width === 0) { + // Exceeded max count of displays + break + } + + var indexToAdd = 0 + for (var j = 0; j < resolutionComboBox.count; j++) { + var existing_width = parseInt(resolutionListModel.get(j).video_width); + var existing_height = parseInt(resolutionListModel.get(j).video_height); + + if (screenRect.width * screenRect.height === existing_width * existing_height) { + // Duplicate entry, skip + indexToAdd = -1 + break + } + else if (screenRect.width * screenRect.height > existing_width * existing_height) { + // Candidate entrypoint after this entry + indexToAdd = j + 1 + } + } + + // Insert this display's resolution if it's not a duplicate + if (indexToAdd >= 0) { + resolutionListModel.insert(indexToAdd, + { + "text": "Native ("+screenRect.width+"x"+screenRect.height+")", + "video_width": ""+screenRect.width, + "video_height": ""+screenRect.height + }) + } + } + // load the saved width/height, and iterate through the ComboBox until a match is found // and set it to that index. var saved_width = prefs.width @@ -63,17 +98,21 @@ ScrollView { for (var i = 0; i < resolutionComboBox.count; i++) { var el_width = parseInt(resolutionListModel.get(i).video_width); var el_height = parseInt(resolutionListModel.get(i).video_height); - if (saved_width === el_width && saved_height === el_height) { + + // Pick the highest value lesser or equal to the saved resolution + if (saved_width * saved_height >= el_width * el_height) { currentIndex = i } } } id: resolutionComboBox - font.pointSize: 9 + width: 200 textRole: "text" model: ListModel { id: resolutionListModel + // Other elements may be added at runtime + // based on attached display resolution ListElement { text: "720p" video_width: "1280" @@ -121,14 +160,15 @@ ScrollView { currentIndex = 0 for (var i = 0; i < fpsComboBox.count; i++) { var el_fps = parseInt(fpsListModel.get(i).video_fps); - if (el_fps === saved_fps) { + + // Pick the highest value lesser or equal to the saved FPS + if (el_fps >= saved_fps) { currentIndex = i } } } id: fpsComboBox - font.pointSize: 9 textRole: "text" model: ListModel { id: fpsListModel @@ -238,7 +278,6 @@ ScrollView { id: audioComboBox width: Math.min(bitrateDesc.implicitWidth, parent.width) - font.pointSize: 9 textRole: "text" model: ListModel { id: audioListModel @@ -362,7 +401,6 @@ ScrollView { id: decoderComboBox width: Math.min(bitrateDesc.implicitWidth, parent.width) - font.pointSize: 9 textRole: "text" model: ListModel { id: decoderListModel @@ -409,7 +447,6 @@ ScrollView { id: codecComboBox width: Math.min(bitrateDesc.implicitWidth, parent.width) - font.pointSize: 9 textRole: "text" model: ListModel { id: codecListModel diff --git a/app/settings/streamingpreferences.cpp b/app/settings/streamingpreferences.cpp index c50f4f81..f7bd5521 100644 --- a/app/settings/streamingpreferences.cpp +++ b/app/settings/streamingpreferences.cpp @@ -93,15 +93,50 @@ int StreamingPreferences::getMaximumStreamingFrameRate() return maxFrameRate; } +QRect StreamingPreferences::getDisplayResolution(int displayIndex) +{ + if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "SDL_InitSubSystem(SDL_INIT_VIDEO) failed: %s", + SDL_GetError()); + return QRect(); + } + + if (displayIndex >= SDL_GetNumVideoDisplays()) { + SDL_QuitSubSystem(SDL_INIT_VIDEO); + return QRect(); + } + + SDL_DisplayMode mode; + int err = SDL_GetCurrentDisplayMode(displayIndex, &mode); + SDL_QuitSubSystem(SDL_INIT_VIDEO); + + if (err == 0) { + return QRect(0, 0, mode.w, mode.h); + } + else { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "SDL_GetCurrentDisplayMode() failed: %s", + SDL_GetError()); + return QRect(); + } +} + int StreamingPreferences::getDefaultBitrate(int width, int height, int fps) { - if (width * height <= 1280 * 720) { + // This table prefers 16:10 resolutions because they are + // only slightly more pixels than the 16:9 equivalents, so + // we don't want to bump those 16:10 resolutions up to the + // next 16:9 slot. + + // This covers 1280x720 and 1280x800 too + if (width * height <= 1366 * 768) { return static_cast(5000 * (fps / 30.0)); } - else if (width * height <= 1920 * 1080) { + else if (width * height <= 1920 * 1200) { return static_cast(10000 * (fps / 30.0)); } - else if (width * height <= 2560 * 1440) { + else if (width * height <= 2560 * 1600) { return static_cast(20000 * (fps / 30.0)); } else /* if (width * height <= 3840 * 2160) */ { diff --git a/app/settings/streamingpreferences.h b/app/settings/streamingpreferences.h index 8ec44d36..3a5d8651 100644 --- a/app/settings/streamingpreferences.h +++ b/app/settings/streamingpreferences.h @@ -1,6 +1,7 @@ #pragma once #include +#include class StreamingPreferences : public QObject { @@ -18,6 +19,8 @@ public: Q_INVOKABLE static int getMaximumStreamingFrameRate(); + Q_INVOKABLE QRect getDisplayResolution(int displayIndex); + void reload(); enum AudioConfig diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index 7029abd2..afe49376 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -450,6 +450,24 @@ void Session::getWindowDimensions(bool fullScreen, { int displayIndex = 0; + // If there's a display matching this exact resolution, pick that + // one (for native full-screen streaming). Otherwise, assume + // display 0 for now. TODO: Default to the screen that the Qt window is on + if (fullScreen) { + for (int i = 0; i < SDL_GetNumVideoDisplays(); i++) { + SDL_DisplayMode mode; + if (SDL_GetCurrentDisplayMode(i, &mode) == 0 && + m_ActiveVideoWidth == mode.w && + m_ActiveVideoHeight == mode.h) { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Found exact resolution match on display: %d", + i); + displayIndex = i; + break; + } + } + } + if (m_Window != nullptr) { displayIndex = SDL_GetWindowDisplayIndex(m_Window); if (displayIndex < 0) {