|
424 | 424 | "SegmentLength": 6 |
425 | 425 | } |
426 | 426 |
|
427 | | - ' Add height restriction if configured |
428 | | - maxHeightArray = getMaxHeightArray(true) |
429 | | - if maxHeightArray.count() > 0 |
430 | | - profile.Conditions = [maxHeightArray] |
| 427 | + ' Add resolution restriction if configured |
| 428 | + resolutionConditions = getResolutionConditions(true) |
| 429 | + if resolutionConditions.count() > 0 |
| 430 | + profile.Conditions = resolutionConditions |
431 | 431 | end if |
432 | 432 |
|
433 | 433 | transcodingProfiles.push(profile) |
|
457 | 457 | "av1": {} |
458 | 458 | } |
459 | 459 | di = CreateObject("roDeviceInfo") |
460 | | - maxHeightArray = getMaxHeightArray() |
| 460 | + resolutionConditions = getResolutionConditions() |
461 | 461 |
|
462 | 462 | ' ======================================== |
463 | 463 | ' DETECT SURROUND PASSTHROUGH SUPPORT |
|
738 | 738 | end if |
739 | 739 |
|
740 | 740 | ' set max resolution |
741 | | - if maxHeightArray.count() > 0 |
742 | | - h264ProfileArray.Conditions.push(maxHeightArray) |
743 | | - end if |
| 741 | + h264ProfileArray.Conditions.Append(resolutionConditions) |
744 | 742 |
|
745 | 743 | ' set bitrate restrictions based on user settings |
746 | 744 | bitRateArray = GetBitRateLimit("h264") |
|
774 | 772 | } |
775 | 773 |
|
776 | 774 | ' set max resolution |
777 | | - if maxHeightArray.count() > 0 |
778 | | - mpeg2ProfileArray.Conditions.push(maxHeightArray) |
779 | | - end if |
| 775 | + mpeg2ProfileArray.Conditions.Append(resolutionConditions) |
780 | 776 |
|
781 | 777 | ' set bitrate restrictions based on user settings |
782 | 778 | bitRateArray = GetBitRateLimit("mpeg2") |
|
826 | 822 | } |
827 | 823 |
|
828 | 824 | ' set max resolution |
829 | | - if maxHeightArray.count() > 0 |
830 | | - av1ProfileArray.Conditions.push(maxHeightArray) |
831 | | - end if |
| 825 | + av1ProfileArray.Conditions.Append(resolutionConditions) |
832 | 826 |
|
833 | 827 | ' set bitrate restrictions based on user settings |
834 | 828 | bitRateArray = GetBitRateLimit("av1") |
|
891 | 885 | end if |
892 | 886 |
|
893 | 887 | ' set max resolution |
894 | | - if maxHeightArray.count() > 0 |
895 | | - hevcProfileArray.Conditions.push(maxHeightArray) |
896 | | - end if |
| 888 | + hevcProfileArray.Conditions.Append(resolutionConditions) |
897 | 889 |
|
898 | 890 | ' set bitrate restrictions based on user settings |
899 | 891 | bitRateArray = GetBitRateLimit("h265") |
|
931 | 923 | } |
932 | 924 |
|
933 | 925 | ' set max resolution |
934 | | - if maxHeightArray.count() > 0 |
935 | | - vp9ProfileArray.Conditions.push(maxHeightArray) |
936 | | - end if |
| 926 | + vp9ProfileArray.Conditions.Append(resolutionConditions) |
937 | 927 |
|
938 | 928 | ' set bitrate restrictions based on user settings |
939 | 929 | bitRateArray = GetBitRateLimit("vp9") |
|
1026 | 1016 | return {} |
1027 | 1017 | end function |
1028 | 1018 |
|
1029 | | -function getMaxHeightArray(isRequired = false as boolean) as object |
| 1019 | +function getResolutionConditions(isRequired = false as boolean) as object |
1030 | 1020 | userMaxHeight = m.global.user.settings.playbackResolutionMax |
1031 | 1021 | if userMaxHeight = invalid or userMaxHeight = "" then userMaxHeight = "auto" |
1032 | | - if userMaxHeight = "off" then return {} |
| 1022 | + if userMaxHeight = "off" then return [] |
1033 | 1023 |
|
1034 | | - deviceMaxHeight = m.global.device.videoHeight |
| 1024 | + globalDevice = m.global.device ' cache - accessed twice below |
| 1025 | + deviceMaxHeight = globalDevice.videoHeight |
1035 | 1026 |
|
1036 | 1027 | maxVideoHeight = 1080 ' default to 1080p in case all our validation checks fail |
| 1028 | + maxVideoWidth = 1920 |
1037 | 1029 |
|
1038 | 1030 | if userMaxHeight = "auto" |
1039 | 1031 | if isValid(deviceMaxHeight) and deviceMaxHeight <> 0 and deviceMaxHeight > maxVideoHeight |
1040 | 1032 | maxVideoHeight = deviceMaxHeight |
| 1033 | + maxVideoWidth = globalDevice.videoWidth ' paired width for device's native video mode |
1041 | 1034 | end if |
1042 | 1035 | else |
1043 | 1036 | userMaxHeight = userMaxHeight.ToInt() |
1044 | 1037 | if isValid(userMaxHeight) and userMaxHeight > 0 and userMaxHeight < maxVideoHeight |
1045 | 1038 | maxVideoHeight = userMaxHeight |
| 1039 | + ' Settings only stores height, so derive the paired 16:9 width |
| 1040 | + ' (same standard resolution pairs as SaveDeviceToGlobal in globals.bs) |
| 1041 | + heightToWidth = { |
| 1042 | + "480": 720, |
| 1043 | + "576": 720, |
| 1044 | + "720": 1280, |
| 1045 | + "1080": 1920, |
| 1046 | + "2160": 3840, |
| 1047 | + "4320": 7680 |
| 1048 | + } |
| 1049 | + mappedWidth = heightToWidth[maxVideoHeight.toStr()] |
| 1050 | + maxVideoWidth = isValid(mappedWidth) ? mappedWidth : int(maxVideoHeight * 16 / 9) |
1046 | 1051 | end if |
1047 | 1052 | end if |
1048 | 1053 |
|
1049 | | - return { |
| 1054 | + return [ |
| 1055 | + { |
| 1056 | + "Condition": "LessThanEqual", |
| 1057 | + "Property": "Height", |
| 1058 | + "Value": maxVideoHeight.toStr(), |
| 1059 | + "IsRequired": isRequired |
| 1060 | + }, |
| 1061 | + { |
| 1062 | + "Condition": "LessThanEqual", |
| 1063 | + "Property": "Width", |
| 1064 | + "Value": maxVideoWidth.toStr(), |
| 1065 | + "IsRequired": isRequired |
| 1066 | + } |
| 1067 | + ] |
| 1068 | +end function |
| 1069 | + |
| 1070 | +' Apply a paired Height + Width resolution cap to a codec profile's Conditions. |
| 1071 | +' No-ops if a Height condition at or below maxHeight already exists. |
| 1072 | +' @param codecProfile {object} - The codec profile AA containing a Conditions array |
| 1073 | +' @param maxHeight {integer} - The max height to cap at (e.g. 1080) |
| 1074 | +' @param maxWidth {integer} - The max width to cap at (e.g. 1920) |
| 1075 | +' @param isRequired {boolean} - Whether the condition is required for direct play |
| 1076 | +sub applyResolutionCapToProfile(codecProfile as object, maxHeight as integer, maxWidth as integer, isRequired = false as boolean) |
| 1077 | + if not isValid(codecProfile) or not isValid(codecProfile.Conditions) then return |
| 1078 | + |
| 1079 | + for each condition in codecProfile.Conditions |
| 1080 | + if isValid(condition.Property) and condition.Property = "Height" |
| 1081 | + if condition.Value.toInt() <= maxHeight |
| 1082 | + return ' Resolution cap already present |
| 1083 | + end if |
| 1084 | + end if |
| 1085 | + end for |
| 1086 | + |
| 1087 | + codecProfile.Conditions.push({ |
1050 | 1088 | "Condition": "LessThanEqual", |
1051 | 1089 | "Property": "Height", |
1052 | | - "Value": maxVideoHeight.toStr(), |
| 1090 | + "Value": maxHeight.toStr(), |
1053 | 1091 | "IsRequired": isRequired |
1054 | | - } |
1055 | | -end function |
| 1092 | + }) |
| 1093 | + codecProfile.Conditions.push({ |
| 1094 | + "Condition": "LessThanEqual", |
| 1095 | + "Property": "Width", |
| 1096 | + "Value": maxWidth.toStr(), |
| 1097 | + "IsRequired": isRequired |
| 1098 | + }) |
| 1099 | +end sub |
1056 | 1100 |
|
1057 | | -' Recieves and returns an assArray of supported profiles and levels for each video codec |
| 1101 | +' Receives and returns an assArray of supported profiles and levels for each video codec |
1058 | 1102 | function updateProfileArray(profileArray as object, videoCodec as string, videoProfile as string, profileLevel = "" as string) as object |
1059 | 1103 | ' validate params |
1060 | 1104 | if not isValid(profileArray) then return {} |
|
0 commit comments