mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2026-06-17 14:11:33 +00:00
Plumb several new options into stream config and launch requests: optimizeGameSettings, playAudioOnPC, surround sound, and HDR
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#import "HttpResponse.h"
|
#import "HttpResponse.h"
|
||||||
#import "HttpRequest.h"
|
#import "HttpRequest.h"
|
||||||
|
#import "StreamConfiguration.h"
|
||||||
|
|
||||||
@interface HttpManager : NSObject <NSURLSessionDelegate>
|
@interface HttpManager : NSObject <NSURLSessionDelegate>
|
||||||
|
|
||||||
@@ -21,8 +22,8 @@
|
|||||||
- (NSURLRequest*) newAppListRequest;
|
- (NSURLRequest*) newAppListRequest;
|
||||||
- (NSURLRequest*) newServerInfoRequest;
|
- (NSURLRequest*) newServerInfoRequest;
|
||||||
- (NSURLRequest*) newHttpServerInfoRequest;
|
- (NSURLRequest*) newHttpServerInfoRequest;
|
||||||
- (NSURLRequest*) newLaunchRequest:(NSString*)appId width:(int)width height:(int)height refreshRate:(int)refreshRate rikey:(NSString*)rikey rikeyid:(int)rikeyid gamepadMask:(int)gamepadMask;
|
- (NSURLRequest*) newLaunchRequest:(StreamConfiguration*)config;
|
||||||
- (NSURLRequest*) newResumeRequestWithRiKey:(NSString*)riKey riKeyId:(int)riKeyId;
|
- (NSURLRequest*) newResumeRequest:(StreamConfiguration*)config;
|
||||||
- (NSURLRequest*) newQuitAppRequest;
|
- (NSURLRequest*) newQuitAppRequest;
|
||||||
- (NSURLRequest*) newAppAssetRequestWithAppId:(NSString*)appId;
|
- (NSURLRequest*) newAppAssetRequestWithAppId:(NSString*)appId;
|
||||||
- (void) executeRequestSynchronously:(HttpRequest*)request;
|
- (void) executeRequestSynchronously:(HttpRequest*)request;
|
||||||
|
|||||||
@@ -167,14 +167,26 @@ static const NSString* HTTPS_PORT = @"47984";
|
|||||||
return [self createRequestFromString:urlString enableTimeout:TRUE];
|
return [self createRequestFromString:urlString enableTimeout:TRUE];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSURLRequest*) newLaunchRequest:(NSString*)appId width:(int)width height:(int)height refreshRate:(int)refreshRate rikey:(NSString*)rikey rikeyid:(int)rikeyid gamepadMask:(int)gamepadMask {
|
- (NSURLRequest*) newLaunchRequest:(StreamConfiguration*)config {
|
||||||
NSString* urlString = [NSString stringWithFormat:@"%@/launch?uniqueid=%@&appid=%@&mode=%dx%dx%d&additionalStates=1&sops=1&rikey=%@&rikeyid=%d&remoteControllersBitmap=%d&gcmap=%d", _baseHTTPSURL, _uniqueId, appId, width, height, refreshRate, rikey, rikeyid, gamepadMask, gamepadMask];
|
NSString* urlString = [NSString stringWithFormat:@"%@/launch?uniqueid=%@&appid=%@&mode=%dx%dx%d&additionalStates=1&sops=%d&rikey=%@&rikeyid=%d%@&localAudioPlayMode=%d&surroundAudioInfo=%d&remoteControllersBitmap=%d&gcmap=%d",
|
||||||
|
_baseHTTPSURL, _uniqueId,
|
||||||
|
config.appID,
|
||||||
|
config.width, config.height, config.frameRate,
|
||||||
|
config.optimizeGameSettings ? 1 : 0,
|
||||||
|
[Utils bytesToHex:config.riKey], config.riKeyId,
|
||||||
|
config.enableHdr ? @"&hdrMode=1&clientHdrCapVersion=0&clientHdrCapSupportedFlagsInUint32=0&clientHdrCapMetaDataId=NV_STATIC_METADATA_TYPE_1&clientHdrCapDisplayData=0x0x0x0x0x0x0x0x0x0x0": @"",
|
||||||
|
config.playAudioOnPC ? 1 : 0,
|
||||||
|
(config.audioChannelMask << 16) | config.audioChannelCount,
|
||||||
|
config.gamepadMask, config.gamepadMask];
|
||||||
// This blocks while the app is launching
|
// This blocks while the app is launching
|
||||||
return [self createRequestFromString:urlString enableTimeout:FALSE];
|
return [self createRequestFromString:urlString enableTimeout:FALSE];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSURLRequest*) newResumeRequestWithRiKey:(NSString*)riKey riKeyId:(int)riKeyId {
|
- (NSURLRequest*) newResumeRequest:(StreamConfiguration*)config {
|
||||||
NSString* urlString = [NSString stringWithFormat:@"%@/resume?uniqueid=%@&rikey=%@&rikeyid=%d", _baseHTTPSURL, _uniqueId, riKey, riKeyId];
|
NSString* urlString = [NSString stringWithFormat:@"%@/resume?uniqueid=%@&rikey=%@&rikeyid=%d&surroundAudioInfo=%d",
|
||||||
|
_baseHTTPSURL, _uniqueId,
|
||||||
|
[Utils bytesToHex:config.riKey], config.riKeyId,
|
||||||
|
(config.audioChannelMask << 16) | config.audioChannelCount];
|
||||||
// This blocks while the app is resuming
|
// This blocks while the app is resuming
|
||||||
return [self createRequestFromString:urlString enableTimeout:FALSE];
|
return [self createRequestFromString:urlString enableTimeout:FALSE];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,9 @@ int ArInit(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig, v
|
|||||||
// Clear the circular buffer
|
// Clear the circular buffer
|
||||||
audioBufferWriteIndex = audioBufferReadIndex = 0;
|
audioBufferWriteIndex = audioBufferReadIndex = 0;
|
||||||
|
|
||||||
// We only support stereo for now
|
// We only support stereo for now.
|
||||||
|
// TODO: Ensure AudioToolbox's channel mapping matches Opus's
|
||||||
|
// and correct if neccessary.
|
||||||
assert(audioConfiguration == AUDIO_CONFIGURATION_STEREO);
|
assert(audioConfiguration == AUDIO_CONFIGURATION_STEREO);
|
||||||
|
|
||||||
activeChannelCount = opusConfig->channelCount;
|
activeChannelCount = opusConfig->channelCount;
|
||||||
@@ -281,9 +283,20 @@ void ClLogMessage(const char* format, ...)
|
|||||||
_streamConfig.height = config.height;
|
_streamConfig.height = config.height;
|
||||||
_streamConfig.fps = config.frameRate;
|
_streamConfig.fps = config.frameRate;
|
||||||
_streamConfig.bitrate = config.bitRate;
|
_streamConfig.bitrate = config.bitRate;
|
||||||
|
|
||||||
// This will activate the remote streaming optimization in moonlight-common if needed
|
|
||||||
_streamConfig.streamingRemotely = config.streamingRemotely;
|
_streamConfig.streamingRemotely = config.streamingRemotely;
|
||||||
|
_streamConfig.enableHdr = config.enableHdr;
|
||||||
|
|
||||||
|
switch (config.audioChannelCount) {
|
||||||
|
case 2:
|
||||||
|
_streamConfig.audioConfiguration = AUDIO_CONFIGURATION_STEREO;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
_streamConfig.audioConfiguration = AUDIO_CONFIGURATION_51_SURROUND;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log(LOG_E, @"Unknown audio channel count: %d", config.audioChannelCount);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
// On iOS 11, we can use HEVC if the server supports encoding it
|
// On iOS 11, we can use HEVC if the server supports encoding it
|
||||||
@@ -302,6 +315,9 @@ void ClLogMessage(const char* format, ...)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// HEVC must be supported when HDR is enabled
|
||||||
|
assert(!_streamConfig.enableHdr || _streamConfig.supportsHevc);
|
||||||
|
|
||||||
// Use some of the HEVC encoding efficiency improvements to
|
// Use some of the HEVC encoding efficiency improvements to
|
||||||
// reduce bandwidth usage while still gaining some image
|
// reduce bandwidth usage while still gaining some image
|
||||||
// quality improvement.
|
// quality improvement.
|
||||||
|
|||||||
@@ -21,5 +21,10 @@
|
|||||||
@property int streamingRemotely;
|
@property int streamingRemotely;
|
||||||
@property NSData* riKey;
|
@property NSData* riKey;
|
||||||
@property int gamepadMask;
|
@property int gamepadMask;
|
||||||
|
@property BOOL optimizeGameSettings;
|
||||||
|
@property BOOL playAudioOnPC;
|
||||||
|
@property int audioChannelCount;
|
||||||
|
@property int audioChannelMask;
|
||||||
|
@property BOOL enableHdr;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -9,5 +9,5 @@
|
|||||||
#import "StreamConfiguration.h"
|
#import "StreamConfiguration.h"
|
||||||
|
|
||||||
@implementation StreamConfiguration
|
@implementation StreamConfiguration
|
||||||
@synthesize host, appID, width, height, frameRate, bitRate, riKeyId, riKey, gamepadMask, streamingRemotely, appName;
|
@synthesize host, appID, width, height, frameRate, bitRate, riKeyId, riKey, gamepadMask, streamingRemotely, appName, optimizeGameSettings, playAudioOnPC, audioChannelMask, audioChannelCount, enableHdr;
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -104,14 +104,7 @@
|
|||||||
|
|
||||||
- (BOOL) launchApp:(HttpManager*)hMan {
|
- (BOOL) launchApp:(HttpManager*)hMan {
|
||||||
HttpResponse* launchResp = [[HttpResponse alloc] init];
|
HttpResponse* launchResp = [[HttpResponse alloc] init];
|
||||||
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:launchResp withUrlRequest:
|
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:launchResp withUrlRequest:[hMan newLaunchRequest:_config]]];
|
||||||
[hMan newLaunchRequest:_config.appID
|
|
||||||
width:_config.width
|
|
||||||
height:_config.height
|
|
||||||
refreshRate:_config.frameRate
|
|
||||||
rikey:[Utils bytesToHex:_config.riKey]
|
|
||||||
rikeyid:_config.riKeyId
|
|
||||||
gamepadMask:_config.gamepadMask]]];
|
|
||||||
NSString *gameSession = [launchResp getStringTag:@"gamesession"];
|
NSString *gameSession = [launchResp getStringTag:@"gamesession"];
|
||||||
if (launchResp == NULL || ![launchResp isStatusOk]) {
|
if (launchResp == NULL || ![launchResp isStatusOk]) {
|
||||||
[_callbacks launchFailed:@"Failed to launch app"];
|
[_callbacks launchFailed:@"Failed to launch app"];
|
||||||
@@ -128,9 +121,7 @@
|
|||||||
|
|
||||||
- (BOOL) resumeApp:(HttpManager*)hMan {
|
- (BOOL) resumeApp:(HttpManager*)hMan {
|
||||||
HttpResponse* resumeResp = [[HttpResponse alloc] init];
|
HttpResponse* resumeResp = [[HttpResponse alloc] init];
|
||||||
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:resumeResp withUrlRequest:
|
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:resumeResp withUrlRequest:[hMan newResumeRequest:_config]]];
|
||||||
[hMan newResumeRequestWithRiKey:[Utils bytesToHex:_config.riKey]
|
|
||||||
riKeyId:_config.riKeyId]]];
|
|
||||||
NSString* resume = [resumeResp getStringTag:@"resume"];
|
NSString* resume = [resumeResp getStringTag:@"resume"];
|
||||||
if (resumeResp == NULL || ![resumeResp isStatusOk]) {
|
if (resumeResp == NULL || ![resumeResp isStatusOk]) {
|
||||||
[_callbacks launchFailed:@"Failed to resume app"];
|
[_callbacks launchFailed:@"Failed to resume app"];
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
#import "IdManager.h"
|
#import "IdManager.h"
|
||||||
#import "ConnectionHelper.h"
|
#import "ConnectionHelper.h"
|
||||||
|
|
||||||
|
#import <VideoToolbox/VideoToolbox.h>
|
||||||
|
|
||||||
@implementation MainFrameViewController {
|
@implementation MainFrameViewController {
|
||||||
NSOperationQueue* _opQueue;
|
NSOperationQueue* _opQueue;
|
||||||
TemporaryHost* _selectedHost;
|
TemporaryHost* _selectedHost;
|
||||||
@@ -432,6 +434,27 @@ static NSMutableSet* hostList;
|
|||||||
_streamConfig.width = [streamSettings.width intValue];
|
_streamConfig.width = [streamSettings.width intValue];
|
||||||
_streamConfig.gamepadMask = [ControllerSupport getConnectedGamepadMask];
|
_streamConfig.gamepadMask = [ControllerSupport getConnectedGamepadMask];
|
||||||
_streamConfig.streamingRemotely = [streamSettings.streamingRemotely intValue];
|
_streamConfig.streamingRemotely = [streamSettings.streamingRemotely intValue];
|
||||||
|
_streamConfig.optimizeGameSettings = YES;
|
||||||
|
_streamConfig.playAudioOnPC = NO;
|
||||||
|
|
||||||
|
// TODO: Detect attached surround sound system then address 5.1 TODOs
|
||||||
|
// in Connection.m
|
||||||
|
_streamConfig.audioChannelCount = 2;
|
||||||
|
_streamConfig.audioChannelMask = 0x3;
|
||||||
|
|
||||||
|
// HDR requires HDR10 game, HDR10 display, and HEVC Main10 decoder on the client.
|
||||||
|
// It additionally requires an HEVC Main10 encoder on the server (GTX 1000+).
|
||||||
|
//
|
||||||
|
// It should also be a user preference when supported, since some games may require
|
||||||
|
// higher peak brightness than the iOS device can support to look correct in HDR mode.
|
||||||
|
if (@available(iOS 11.3, *)) {
|
||||||
|
_streamConfig.enableHdr =
|
||||||
|
app.hdrSupported && // App supported
|
||||||
|
(app.host.serverCodecModeSupport & 0x200) != 0 && // HEVC Main10 encoding on host PC GPU
|
||||||
|
VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC) && // Decoder supported
|
||||||
|
(AVPlayer.availableHDRModes & AVPlayerHDRModeHDR10) != 0 && // Display supported
|
||||||
|
NO; // TODO: User wants it enabled
|
||||||
|
}
|
||||||
|
|
||||||
[_appManager stopRetrieving];
|
[_appManager stopRetrieving];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user