diff --git a/Limelight/Database/DataManager.h b/Limelight/Database/DataManager.h
index d7d4d5e..5717a79 100644
--- a/Limelight/Database/DataManager.h
+++ b/Limelight/Database/DataManager.h
@@ -23,7 +23,7 @@
multiController:(BOOL)multiController
swapABXYButtons:(BOOL)swapABXYButtons
audioOnPC:(BOOL)audioOnPC
- useHevc:(BOOL)useHevc
+ preferredCodec:(uint32_t)preferredCodec
useFramePacing:(BOOL)useFramePacing
enableHdr:(BOOL)enableHdr
btMouseSupport:(BOOL)btMouseSupport
diff --git a/Limelight/Database/DataManager.m b/Limelight/Database/DataManager.m
index 1c3144a..0f5edeb 100644
--- a/Limelight/Database/DataManager.m
+++ b/Limelight/Database/DataManager.m
@@ -62,7 +62,7 @@
multiController:(BOOL)multiController
swapABXYButtons:(BOOL)swapABXYButtons
audioOnPC:(BOOL)audioOnPC
- useHevc:(BOOL)useHevc
+ preferredCodec:(uint32_t)preferredCodec
useFramePacing:(BOOL)useFramePacing
enableHdr:(BOOL)enableHdr
btMouseSupport:(BOOL)btMouseSupport
@@ -81,7 +81,7 @@
settingsToSave.multiController = multiController;
settingsToSave.swapABXYButtons = swapABXYButtons;
settingsToSave.playAudioOnPC = audioOnPC;
- settingsToSave.useHevc2 = useHevc;
+ settingsToSave.preferredCodec = preferredCodec;
settingsToSave.useFramePacing = useFramePacing;
settingsToSave.enableHdr = enableHdr;
settingsToSave.btMouseSupport = btMouseSupport;
diff --git a/Limelight/Database/TemporarySettings.h b/Limelight/Database/TemporarySettings.h
index 196c689..da35b30 100644
--- a/Limelight/Database/TemporarySettings.h
+++ b/Limelight/Database/TemporarySettings.h
@@ -19,7 +19,12 @@
@property (nonatomic, retain) NSNumber * audioConfig;
@property (nonatomic, retain) NSNumber * onscreenControls;
@property (nonatomic, retain) NSString * uniqueId;
-@property (nonatomic) BOOL useHevc;
+@property (nonatomic) enum {
+ CODEC_PREF_AUTO,
+ CODEC_PREF_H264,
+ CODEC_PREF_HEVC,
+ CODEC_PREF_AV1,
+} preferredCodec;
@property (nonatomic) BOOL useFramePacing;
@property (nonatomic) BOOL multiController;
@property (nonatomic) BOOL swapABXYButtons;
diff --git a/Limelight/Database/TemporarySettings.m b/Limelight/Database/TemporarySettings.m
index 16aaa77..93e01b5 100644
--- a/Limelight/Database/TemporarySettings.m
+++ b/Limelight/Database/TemporarySettings.m
@@ -36,7 +36,7 @@
assert([self.framerate intValue] != 0);
self.audioConfig = [NSNumber numberWithInteger:[[NSUserDefaults standardUserDefaults] integerForKey:@"audioConfig"]];
assert([self.audioConfig intValue] != 0);
- self.useHevc = [[NSUserDefaults standardUserDefaults] boolForKey:@"useHevc2"];
+ self.preferredCodec = [[NSUserDefaults standardUserDefaults] integerForKey:@"preferredCodec"];
self.useFramePacing = [[NSUserDefaults standardUserDefaults] integerForKey:@"useFramePacing"] != 0;
self.playAudioOnPC = [[NSUserDefaults standardUserDefaults] boolForKey:@"audioOnPC"];
self.enableHdr = [[NSUserDefaults standardUserDefaults] boolForKey:@"enableHdr"];
@@ -74,7 +74,7 @@
self.height = settings.height;
self.width = settings.width;
self.audioConfig = settings.audioConfig;
- self.useHevc = settings.useHevc2;
+ self.preferredCodec = settings.preferredCodec;
self.useFramePacing = settings.useFramePacing;
self.playAudioOnPC = settings.playAudioOnPC;
self.enableHdr = settings.enableHdr;
diff --git a/Limelight/Limelight.xcdatamodeld/.xccurrentversion b/Limelight/Limelight.xcdatamodeld/.xccurrentversion
index 4e7ed17..b202eb9 100644
--- a/Limelight/Limelight.xcdatamodeld/.xccurrentversion
+++ b/Limelight/Limelight.xcdatamodeld/.xccurrentversion
@@ -3,6 +3,6 @@
_XCCurrentVersionName
- Moonlight v1.9.xcdatamodel
+ Moonlight v1.10.xcdatamodel
diff --git a/Limelight/Limelight.xcdatamodeld/Moonlight v1.10.xcdatamodel/contents b/Limelight/Limelight.xcdatamodeld/Moonlight v1.10.xcdatamodel/contents
new file mode 100644
index 0000000..a2cc61c
--- /dev/null
+++ b/Limelight/Limelight.xcdatamodeld/Moonlight v1.10.xcdatamodel/contents
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Limelight/ViewControllers/MainFrameViewController.m b/Limelight/ViewControllers/MainFrameViewController.m
index fbef7cb..b900df0 100644
--- a/Limelight/ViewControllers/MainFrameViewController.m
+++ b/Limelight/ViewControllers/MainFrameViewController.m
@@ -662,11 +662,27 @@ static NSMutableSet* hostList;
_streamConfig.serverCodecModeSupport = app.host.serverCodecModeSupport;
- // H.264 is always supported
- _streamConfig.supportedVideoFormats = VIDEO_FORMAT_H264;
+ switch (streamSettings.preferredCodec) {
+ case CODEC_PREF_AV1:
+ if (VTIsHardwareDecodeSupported(kCMVideoCodecType_AV1)) {
+ _streamConfig.supportedVideoFormats |= VIDEO_FORMAT_AV1_MAIN8;
+ }
+ // Fall-through
+
+ case CODEC_PREF_AUTO:
+ case CODEC_PREF_HEVC:
+ if (VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC)) {
+ _streamConfig.supportedVideoFormats |= VIDEO_FORMAT_H265;
+ }
+ // Fall-through
+
+ case CODEC_PREF_H264:
+ _streamConfig.supportedVideoFormats |= VIDEO_FORMAT_H264;
+ break;
+ }
// HEVC is supported if the user wants it (or it's required by the chosen resolution) and the SoC supports it
- if ((_streamConfig.width > 4096 || _streamConfig.height > 4096 || streamSettings.useHevc || streamSettings.enableHdr) && VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC)) {
+ if ((_streamConfig.width > 4096 || _streamConfig.height > 4096 || streamSettings.enableHdr) && VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC)) {
_streamConfig.supportedVideoFormats |= VIDEO_FORMAT_H265;
// HEVC Main10 is supported if the user wants it and the display supports it
@@ -674,6 +690,12 @@ static NSMutableSet* hostList;
_streamConfig.supportedVideoFormats |= VIDEO_FORMAT_H265_MAIN10;
}
}
+
+ // Add the AV1 Main10 format if AV1 and HDR are both enabled and supported
+ if ((_streamConfig.supportedVideoFormats & VIDEO_FORMAT_MASK_AV1) && streamSettings.enableHdr &&
+ VTIsHardwareDecodeSupported(kCMVideoCodecType_AV1) && (AVPlayer.availableHDRModes & AVPlayerHDRModeHDR10) != 0) {
+ _streamConfig.supportedVideoFormats |= VIDEO_FORMAT_AV1_MAIN10;
+ }
}
- (void)appLongClicked:(TemporaryApp *)app view:(UIView *)view {
diff --git a/Limelight/ViewControllers/SettingsViewController.h b/Limelight/ViewControllers/SettingsViewController.h
index 9bdcf21..1a79162 100644
--- a/Limelight/ViewControllers/SettingsViewController.h
+++ b/Limelight/ViewControllers/SettingsViewController.h
@@ -21,7 +21,7 @@
@property (strong, nonatomic) IBOutlet UISegmentedControl *multiControllerSelector;
@property (strong, nonatomic) IBOutlet UISegmentedControl *swapABXYButtonsSelector;
@property (strong, nonatomic) IBOutlet UISegmentedControl *audioOnPCSelector;
-@property (strong, nonatomic) IBOutlet UISegmentedControl *hevcSelector;
+@property (strong, nonatomic) IBOutlet UISegmentedControl *codecSelector;
@property (strong, nonatomic) IBOutlet UISegmentedControl *hdrSelector;
@property (strong, nonatomic) IBOutlet UISegmentedControl *framePacingSelector;
@property (strong, nonatomic) IBOutlet UISegmentedControl *btMouseSelector;
diff --git a/Limelight/ViewControllers/SettingsViewController.m b/Limelight/ViewControllers/SettingsViewController.m
index 0b83ba5..8e105c8 100644
--- a/Limelight/ViewControllers/SettingsViewController.m
+++ b/Limelight/ViewControllers/SettingsViewController.m
@@ -198,53 +198,43 @@ BOOL isCustomResolution(CGSize res) {
if (!enable120Fps) {
[self.framerateSelector removeSegmentAtIndex:2 animated:NO];
}
-
- // Only show the 4K option for "recent" devices. We'll judge that by whether
- // they support HEVC decoding (A9 or later).
- if (@available(iOS 11.0, tvOS 11.0, *)) {
- if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC)) {
- [self.resolutionSelector setEnabled:NO forSegmentAtIndex:3];
- }
+
+ // Disable codec selector segments for unsupported codecs
+ if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_AV1)) {
+ [self.codecSelector setEnabled:NO forSegmentAtIndex:2];
}
- else {
+ if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC)) {
+ [self.codecSelector setEnabled:NO forSegmentAtIndex:1];
+
+ // Only enable the 4K option for "recent" devices. We'll judge that by whether
+ // they support HEVC decoding (A9 or later).
[self.resolutionSelector setEnabled:NO forSegmentAtIndex:3];
}
-
- // Disable the HEVC selector if HEVC is not supported by the hardware
- // or the version of iOS. See comment in Connection.m for reasoning behind
- // the iOS 11.3 check.
- if (@available(iOS 11.3, tvOS 11.3, *)) {
- if (VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC)) {
- [self.hevcSelector setSelectedSegmentIndex:currentSettings.useHevc ? 1 : 0];
- }
- else {
- [self.hevcSelector removeAllSegments];
- [self.hevcSelector insertSegmentWithTitle:@"Unsupported on this device" atIndex:0 animated:NO];
- [self.hevcSelector setEnabled:NO];
- }
-
- // Disable HDR selector if HDR is not supported by the display
- if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC) || !(AVPlayer.availableHDRModes & AVPlayerHDRModeHDR10)) {
- [self.hdrSelector removeAllSegments];
- [self.hdrSelector insertSegmentWithTitle:@"Unsupported on this device" atIndex:0 animated:NO];
- [self.hdrSelector setEnabled:NO];
- }
- else {
- [self.hdrSelector setSelectedSegmentIndex:currentSettings.enableHdr ? 1 : 0];
- [self.hdrSelector addTarget:self action:@selector(hdrStateChanged) forControlEvents:UIControlEventValueChanged];
+ switch (currentSettings.preferredCodec) {
+ case CODEC_PREF_AUTO:
+ [self.codecSelector setSelectedSegmentIndex:self.codecSelector.numberOfSegments - 1];
+ break;
- // Manually trigger the hdrStateChanged callback to set the HEVC selector appropriately
- [self hdrStateChanged];
- }
+ case CODEC_PREF_AV1:
+ [self.codecSelector setSelectedSegmentIndex:2];
+ break;
+
+ case CODEC_PREF_HEVC:
+ [self.codecSelector setSelectedSegmentIndex:1];
+ break;
+
+ case CODEC_PREF_H264:
+ [self.codecSelector setSelectedSegmentIndex:0];
+ break;
+ }
+
+ if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC) || !(AVPlayer.availableHDRModes & AVPlayerHDRModeHDR10)) {
+ [self.hdrSelector removeAllSegments];
+ [self.hdrSelector insertSegmentWithTitle:@"Unsupported on this device" atIndex:0 animated:NO];
+ [self.hdrSelector setEnabled:NO];
}
else {
- [self.hevcSelector removeAllSegments];
- [self.hevcSelector insertSegmentWithTitle:@"Requires iOS 11.3 or later" atIndex:0 animated:NO];
- [self.hevcSelector setEnabled:NO];
-
- [self.hdrSelector removeAllSegments];
- [self.hdrSelector insertSegmentWithTitle:@"Requires iOS 11.3 or later" atIndex:0 animated:NO];
- [self.hdrSelector setEnabled:NO];
+ [self.hdrSelector setSelectedSegmentIndex:currentSettings.enableHdr ? 1 : 0];
}
[self.touchModeSelector setSelectedSegmentIndex:currentSettings.absoluteTouchMode ? 1 : 0];
@@ -351,16 +341,6 @@ BOOL isCustomResolution(CGSize res) {
}
}
-- (void) hdrStateChanged {
- if ([self.hdrSelector selectedSegmentIndex] == 1) {
- [self.hevcSelector setSelectedSegmentIndex:1];
- [self.hevcSelector setEnabled:NO];
- }
- else {
- [self.hevcSelector setEnabled:YES];
- }
-}
-
- (void) promptCustomResolutionDialog {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Enter Custom Resolution" message:nil preferredStyle:UIAlertControllerStyleAlert];
@@ -497,6 +477,28 @@ BOOL isCustomResolution(CGSize res) {
}
}
+- (uint32_t) getChosenCodecPreference {
+ // Auto is always the last segment
+ if (self.codecSelector.selectedSegmentIndex == self.codecSelector.numberOfSegments - 1) {
+ return CODEC_PREF_AUTO;
+ }
+ else {
+ switch (self.codecSelector.selectedSegmentIndex) {
+ case 0:
+ return CODEC_PREF_H264;
+
+ case 1:
+ return CODEC_PREF_HEVC;
+
+ case 2:
+ return CODEC_PREF_AV1;
+
+ default:
+ abort();
+ }
+ }
+}
+
- (NSInteger) getChosenStreamHeight {
// because the 4k resolution can be removed
BOOL lastSegmentSelected = [self.resolutionSelector selectedSegmentIndex] + 1 == [self.resolutionSelector numberOfSegments];
@@ -527,7 +529,7 @@ BOOL isCustomResolution(CGSize res) {
BOOL multiController = [self.multiControllerSelector selectedSegmentIndex] == 1;
BOOL swapABXYButtons = [self.swapABXYButtonsSelector selectedSegmentIndex] == 1;
BOOL audioOnPC = [self.audioOnPCSelector selectedSegmentIndex] == 1;
- BOOL useHevc = [self.hevcSelector selectedSegmentIndex] == 1;
+ uint32_t preferredCodec = [self getChosenCodecPreference];
BOOL btMouseSupport = [self.btMouseSelector selectedSegmentIndex] == 1;
BOOL useFramePacing = [self.framePacingSelector selectedSegmentIndex] == 1;
BOOL absoluteTouchMode = [self.touchModeSelector selectedSegmentIndex] == 1;
@@ -543,8 +545,8 @@ BOOL isCustomResolution(CGSize res) {
multiController:multiController
swapABXYButtons:swapABXYButtons
audioOnPC:audioOnPC
- useHevc:useHevc
- useFramePacing:useFramePacing
+ preferredCodec:preferredCodec
+ useFramePacing:useFramePacing
enableHdr:enableHdr
btMouseSupport:btMouseSupport
absoluteTouchMode:absoluteTouchMode
diff --git a/Moonlight TV/Settings.bundle/Root.plist b/Moonlight TV/Settings.bundle/Root.plist
index 36193c7..8088188 100644
--- a/Moonlight TV/Settings.bundle/Root.plist
+++ b/Moonlight TV/Settings.bundle/Root.plist
@@ -188,13 +188,25 @@
Type
- PSToggleSwitchSpecifier
+ PSMultiValueSpecifier
Title
- Use HEVC Codec
+ Preferred Codec
Key
- useHevc2
+ preferredCodec
DefaultValue
-
+ 0
+ Values
+
+ 0
+ 1
+ 2
+
+ Titles
+
+ Auto
+ H.264
+ HEVC
+
Type
diff --git a/Moonlight.xcodeproj/project.pbxproj b/Moonlight.xcodeproj/project.pbxproj
index 2968af5..d5a3658 100644
--- a/Moonlight.xcodeproj/project.pbxproj
+++ b/Moonlight.xcodeproj/project.pbxproj
@@ -186,6 +186,7 @@
9865DC3B2132922E0005B9B9 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS11.4.sdk/System/Library/Frameworks/GameController.framework; sourceTree = DEVELOPER_DIR; };
986CCE6C2133E45300168291 /* Moonlight v1.2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Moonlight v1.2.xcdatamodel"; sourceTree = ""; };
986E28A528EA989100758361 /* Moonlight v1.9.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Moonlight v1.9.xcdatamodel"; sourceTree = ""; };
+ 9874E8962AE95E1D00130A3C /* Moonlight v1.10.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Moonlight v1.10.xcdatamodel"; sourceTree = ""; };
98783FEA242EAC5D00F00EF4 /* Moonlight v1.5.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Moonlight v1.5.xcdatamodel"; sourceTree = ""; };
988FCD3F293B091B003050E2 /* KeyboardInputField.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyboardInputField.h; sourceTree = ""; };
988FCD40293B091B003050E2 /* KeyboardInputField.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeyboardInputField.m; sourceTree = ""; };
@@ -1448,6 +1449,7 @@
FB290D0519B2C406004C83CF /* Limelight.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
+ 9874E8962AE95E1D00130A3C /* Moonlight v1.10.xcdatamodel */,
986E28A528EA989100758361 /* Moonlight v1.9.xcdatamodel */,
984CD023288A310D0097D2D4 /* Moonlight v1.8.xcdatamodel */,
566E9D2B2770B23A00EF7BFE /* Moonlight v1.7.xcdatamodel */,
@@ -1463,7 +1465,7 @@
FB4678F21A51BDCB00377732 /* Limelight 0.3.0.xcdatamodel */,
FB290D0619B2C406004C83CF /* Limelight.xcdatamodel */,
);
- currentVersion = 986E28A528EA989100758361 /* Moonlight v1.9.xcdatamodel */;
+ currentVersion = 9874E8962AE95E1D00130A3C /* Moonlight v1.10.xcdatamodel */;
path = Limelight.xcdatamodeld;
sourceTree = "";
versionGroupType = wrapper.xcdatamodel;
diff --git a/iPad.storyboard b/iPad.storyboard
index 1898f86..9017b15 100644
--- a/iPad.storyboard
+++ b/iPad.storyboard
@@ -1,9 +1,9 @@
-
+
-
+
@@ -217,19 +217,21 @@
-
diff --git a/iPhone.storyboard b/iPhone.storyboard
index 65880f3..03aa007 100644
--- a/iPhone.storyboard
+++ b/iPhone.storyboard
@@ -1,9 +1,9 @@
-
+
-
+
@@ -247,19 +247,21 @@
-
-
+
+
-
-
+
+
-
-
+
+
+
+
@@ -340,10 +342,10 @@
+
-