update prefered codecs and maxAudioChannel logic
This commit is contained in:
parent
adc769c625
commit
9c6201b25e
|
@ -52,47 +52,63 @@ function getDeviceProfile() as object
|
|||
playAv1 = m.global.session.user.settings["playback.av1"]
|
||||
di = CreateObject("roDeviceInfo")
|
||||
|
||||
transContainers = ["mp4", "hls", "mkv", "ism", "dash", "ts"]
|
||||
supportedVideoCodecs = {}
|
||||
supportedAudioCodecs = {}
|
||||
addH264Profile = false
|
||||
addHevcProfile = false
|
||||
addMpeg2Profile = false
|
||||
addAv1Profile = false
|
||||
addVp9Profile = false
|
||||
' TRANSCODING
|
||||
' use strings to preserve order
|
||||
mp4AudioCodecs = "aac"
|
||||
mp4VideoCodecs = "h264"
|
||||
tsAudioCodecs = "aac"
|
||||
tsVideoCodecs = "h264"
|
||||
' profileSupport["mp4"]["hevc"]["profile name"]["profile level"]
|
||||
profileSupport = {
|
||||
mp4: {},
|
||||
ts: {}
|
||||
}
|
||||
|
||||
maxAudioChannels = "2"
|
||||
di = CreateObject("roDeviceInfo")
|
||||
|
||||
' does the users setup support surround sound?
|
||||
maxAudioChannels = "2" ' jellyfin expects this as a string
|
||||
' in order of preference from left to right
|
||||
' aac will be highest priority unless surroundSoundCodec <> "aac"
|
||||
audioCodecs = ["mp3", "vorbis", "opus", "flac", "alac", "ac4", "pcm", "wma", "wmapro"]
|
||||
surroundSoundCodecs = ["aac", "eac3", "ac3", "vorbis", "dts"]
|
||||
surroundSoundCodec = invalid
|
||||
if di.GetAudioOutputChannel() = "5.1 surround"
|
||||
maxAudioChannels = "6"
|
||||
eightChannelCodecs = ["ac3", "eac3", "dts"]
|
||||
for each eightChannelCodec in eightChannelCodecs
|
||||
if di.CanDecodeAudio({ Codec: eightChannelCodec, ChCnt: 8 }).Result
|
||||
maxAudioChannels = "8"
|
||||
for each codec in surroundSoundCodecs
|
||||
if di.CanDecodeAudio({ Codec: codec, ChCnt: 6 }).Result
|
||||
surroundSoundCodec = codec
|
||||
if di.CanDecodeAudio({ Codec: codec, ChCnt: 8 }).Result
|
||||
maxAudioChannels = "8"
|
||||
end if
|
||||
exit for
|
||||
end if
|
||||
end for
|
||||
end if
|
||||
|
||||
' AVC / h264
|
||||
' VIDEO CODECS
|
||||
'
|
||||
' AVC / h264 / MPEG4 AVC
|
||||
h264Profiles = ["main", "high"]
|
||||
h264Levels = ["4.1", "4.2"]
|
||||
|
||||
for each container in transContainers
|
||||
for each container in profileSupport
|
||||
for each profile in h264Profiles
|
||||
for each level in h264Levels
|
||||
if di.CanDecodeVideo({ Codec: "h264", Container: container, Profile: profile, Level: level }).Result
|
||||
addH264Profile = true
|
||||
if supportedVideoCodecs[container] = invalid
|
||||
supportedVideoCodecs[container] = {}
|
||||
profileSupport[container] = updateProfileArray(profileSupport[container], "h264", profile, level)
|
||||
end if
|
||||
if di.CanDecodeVideo({ Codec: "mpeg4 avc", Container: container, Profile: profile, Level: level }).Result
|
||||
profileSupport[container] = updateProfileArray(profileSupport[container], "mpeg4 avc", profile, level)
|
||||
if container = "mp4"
|
||||
' check for codec string before adding it
|
||||
if mp4VideoCodecs.Instr(0, ",mpeg4 avc") = -1
|
||||
mp4VideoCodecs = mp4VideoCodecs + ",mpeg4 avc"
|
||||
end if
|
||||
else if container = "ts"
|
||||
' check for codec string before adding it
|
||||
if tsVideoCodecs.Instr(0, ",mpeg4 avc") = -1
|
||||
tsVideoCodecs = tsVideoCodecs + ",mpeg4 avc"
|
||||
end if
|
||||
end if
|
||||
if supportedVideoCodecs[container]["h264"] = invalid
|
||||
supportedVideoCodecs[container]["h264"] = {}
|
||||
end if
|
||||
if supportedVideoCodecs[container]["h264"][profile] = invalid
|
||||
supportedVideoCodecs[container]["h264"][profile] = []
|
||||
end if
|
||||
supportedVideoCodecs[container]["h264"][profile].push(level)
|
||||
end if
|
||||
end for
|
||||
end for
|
||||
|
@ -101,53 +117,80 @@ function getDeviceProfile() as object
|
|||
' HEVC / h265
|
||||
hevcProfiles = ["main", "main 10"]
|
||||
hevcLevels = ["4.1", "5.0", "5.1"]
|
||||
|
||||
for each container in transContainers
|
||||
addHevc = false
|
||||
for each container in profileSupport
|
||||
for each profile in hevcProfiles
|
||||
for each level in hevcLevels
|
||||
if di.CanDecodeVideo({ Codec: "hevc", Container: container, Profile: profile, Level: level }).Result
|
||||
addHevcProfile = true
|
||||
' hevc codec string
|
||||
if supportedVideoCodecs[container] = invalid
|
||||
supportedVideoCodecs[container] = {}
|
||||
addHevc = true
|
||||
profileSupport[container] = updateProfileArray(profileSupport[container], "hevc", profile, level)
|
||||
profileSupport[container] = updateProfileArray(profileSupport[container], "h265", profile, level)
|
||||
if container = "mp4"
|
||||
' check for codec string before adding it
|
||||
if mp4VideoCodecs.Instr(0, "h265,") = -1
|
||||
mp4VideoCodecs = "h265," + mp4VideoCodecs
|
||||
end if
|
||||
if mp4VideoCodecs.Instr(0, "hevc,") = -1
|
||||
mp4VideoCodecs = "hevc," + mp4VideoCodecs
|
||||
end if
|
||||
else if container = "ts"
|
||||
' check for codec string before adding it
|
||||
if tsVideoCodecs.Instr(0, "h265,") = -1
|
||||
tsVideoCodecs = "h265," + tsVideoCodecs
|
||||
end if
|
||||
if tsVideoCodecs.Instr(0, "hevc,") = -1
|
||||
tsVideoCodecs = "hevc," + tsVideoCodecs
|
||||
end if
|
||||
end if
|
||||
if supportedVideoCodecs[container]["hevc"] = invalid
|
||||
supportedVideoCodecs[container]["hevc"] = {}
|
||||
end if
|
||||
if supportedVideoCodecs[container]["hevc"][profile] = invalid
|
||||
supportedVideoCodecs[container]["hevc"][profile] = []
|
||||
end if
|
||||
supportedVideoCodecs[container]["hevc"][profile].push(level)
|
||||
' h265 codec string
|
||||
if supportedVideoCodecs[container] = invalid
|
||||
supportedVideoCodecs[container] = {}
|
||||
end if
|
||||
if supportedVideoCodecs[container]["h265"] = invalid
|
||||
supportedVideoCodecs[container]["h265"] = {}
|
||||
end if
|
||||
if supportedVideoCodecs[container]["h265"][profile] = invalid
|
||||
supportedVideoCodecs[container]["h265"][profile] = []
|
||||
end if
|
||||
supportedVideoCodecs[container]["h265"][profile].push(level)
|
||||
end if
|
||||
end for
|
||||
end for
|
||||
end for
|
||||
|
||||
' VP9
|
||||
vp9Profiles = ["profile 0", "profile 2"]
|
||||
addVp9 = false
|
||||
for each container in profileSupport
|
||||
for each profile in vp9Profiles
|
||||
if di.CanDecodeAudio({ Codec: "vp9", Container: container, Profile: profile }).Result
|
||||
addVp9 = true
|
||||
profileSupport[container] = updateProfileArray(profileSupport[container], "vp9", profile)
|
||||
|
||||
if container = "mp4"
|
||||
' check for codec string before adding it
|
||||
if mp4VideoCodecs.Instr(0, ",vp9") = -1
|
||||
mp4VideoCodecs = mp4VideoCodecs + ",vp9"
|
||||
end if
|
||||
else if container = "ts"
|
||||
' check for codec string before adding it
|
||||
if tsVideoCodecs.Instr(0, ",vp9") = -1
|
||||
tsVideoCodecs = tsVideoCodecs + ",vp9"
|
||||
end if
|
||||
end if
|
||||
end if
|
||||
end for
|
||||
end for
|
||||
|
||||
' MPEG2
|
||||
mpeg2Levels = ["main", "high"]
|
||||
mpeg2Profiles = ["main", "high"]
|
||||
addMpeg2 = false
|
||||
if playMpeg2
|
||||
for each container in transContainers
|
||||
for each level in mpeg2Levels
|
||||
if di.CanDecodeVideo({ Codec: "mpeg2", Container: container, Level: level }).Result
|
||||
addMpeg2Profile = true
|
||||
if supportedVideoCodecs[container] = invalid
|
||||
supportedVideoCodecs[container] = {}
|
||||
for each container in profileSupport
|
||||
for each profile in mpeg2Profiles
|
||||
if di.CanDecodeVideo({ Codec: "mpeg2", Container: container, Profile: profile }).Result
|
||||
addMpeg2 = true
|
||||
profileSupport[container] = updateProfileArray(profileSupport[container], "mpeg2", profile)
|
||||
if container = "mp4"
|
||||
' check for codec string before adding it
|
||||
if mp4VideoCodecs.Instr(0, ",mpeg2video") = -1
|
||||
mp4VideoCodecs = mp4VideoCodecs + ",mpeg2video"
|
||||
end if
|
||||
else if container = "ts"
|
||||
' check for codec string before adding it
|
||||
if tsVideoCodecs.Instr(0, ",mpeg2video") = -1
|
||||
tsVideoCodecs = tsVideoCodecs + ",mpeg2video"
|
||||
end if
|
||||
end if
|
||||
if supportedVideoCodecs[container]["mpeg2video"] = invalid
|
||||
supportedVideoCodecs[container]["mpeg2video"] = []
|
||||
end if
|
||||
supportedVideoCodecs[container]["mpeg2video"].push(level)
|
||||
end if
|
||||
end for
|
||||
end for
|
||||
|
@ -156,153 +199,72 @@ function getDeviceProfile() as object
|
|||
' AV1
|
||||
av1Profiles = ["main", "main 10"]
|
||||
av1Levels = ["4.1", "5.0", "5.1"]
|
||||
addAv1 = false
|
||||
if playAv1
|
||||
for each container in transContainers
|
||||
for each container in profileSupport
|
||||
for each profile in av1Profiles
|
||||
for each level in av1Levels
|
||||
if di.CanDecodeVideo({ Codec: "av1", Container: container, Profile: profile, Level: level }).Result
|
||||
addAv1Profile = true
|
||||
' av1 codec string
|
||||
if supportedVideoCodecs[container] = invalid
|
||||
supportedVideoCodecs[container] = {}
|
||||
addAv1 = true
|
||||
profileSupport[container] = updateProfileArray(profileSupport[container], "av1", profile, level)
|
||||
if container = "mp4"
|
||||
' check for codec string before adding it
|
||||
if mp4VideoCodecs.Instr(0, ",av1") = -1
|
||||
mp4VideoCodecs = mp4VideoCodecs + ",av1"
|
||||
end if
|
||||
else if container = "ts"
|
||||
' check for codec string before adding it
|
||||
if tsVideoCodecs.Instr(0, ",av1") = -1
|
||||
tsVideoCodecs = tsVideoCodecs + ",av1"
|
||||
end if
|
||||
end if
|
||||
if supportedVideoCodecs[container]["av1"] = invalid
|
||||
supportedVideoCodecs[container]["av1"] = {}
|
||||
end if
|
||||
if supportedVideoCodecs[container]["av1"][profile] = invalid
|
||||
supportedVideoCodecs[container]["av1"][profile] = []
|
||||
end if
|
||||
supportedVideoCodecs[container]["av1"][profile].push(level)
|
||||
end if
|
||||
end for
|
||||
end for
|
||||
end for
|
||||
end if
|
||||
|
||||
' VP9
|
||||
vp9Profiles = ["profile 0", "profile 2"]
|
||||
|
||||
for each container in transContainers
|
||||
for each profile in vp9Profiles
|
||||
if di.CanDecodeVideo({ Codec: "vp9", Container: container, Profile: profile }).Result
|
||||
addVp9Profile = true
|
||||
' vp9 codec string
|
||||
if supportedVideoCodecs[container] = invalid
|
||||
supportedVideoCodecs[container] = {}
|
||||
' AUDIO CODECS
|
||||
for each container in profileSupport
|
||||
for each codec in audioCodecs
|
||||
if di.CanDecodeAudio({ Codec: codec, Container: container }).result
|
||||
if container = "mp4"
|
||||
' check for codec string before adding it
|
||||
if mp4VideoCodecs.Instr(0, "," + codec) = -1
|
||||
mp4AudioCodecs = mp4AudioCodecs + "," + codec
|
||||
end if
|
||||
else if container = "ts"
|
||||
' check for codec string before adding it
|
||||
if tsAudioCodecs.Instr(0, "," + codec) = -1
|
||||
tsAudioCodecs = tsAudioCodecs + "," + codec
|
||||
end if
|
||||
end if
|
||||
if supportedVideoCodecs[container]["vp9"] = invalid
|
||||
supportedVideoCodecs[container]["vp9"] = []
|
||||
end if
|
||||
supportedVideoCodecs[container]["vp9"].push(profile)
|
||||
end if
|
||||
end for
|
||||
end for
|
||||
|
||||
' eac3
|
||||
for each container in transContainers
|
||||
if di.CanDecodeAudio({ Codec: "eac3", Container: container }).result
|
||||
if supportedAudioCodecs[container] = invalid
|
||||
supportedAudioCodecs[container] = []
|
||||
end if
|
||||
|
||||
supportedAudioCodecs[container].push("eac3")
|
||||
end if
|
||||
end for
|
||||
|
||||
|
||||
' ac3
|
||||
for each container in transContainers
|
||||
if di.CanDecodeAudio({ Codec: "ac3", Container: container }).result
|
||||
if supportedAudioCodecs[container] = invalid
|
||||
supportedAudioCodecs[container] = []
|
||||
end if
|
||||
|
||||
supportedAudioCodecs[container].push("ac3")
|
||||
end if
|
||||
end for
|
||||
|
||||
' dts
|
||||
for each container in transContainers
|
||||
if di.CanDecodeAudio({ Codec: "dts", Container: container }).result
|
||||
if supportedAudioCodecs[container] = invalid
|
||||
supportedAudioCodecs[container] = []
|
||||
end if
|
||||
|
||||
supportedAudioCodecs[container].push("dts")
|
||||
end if
|
||||
end for
|
||||
|
||||
' opus
|
||||
for each container in transContainers
|
||||
if di.CanDecodeAudio({ Codec: "opus", Container: container }).result
|
||||
if supportedAudioCodecs[container] = invalid
|
||||
supportedAudioCodecs[container] = []
|
||||
end if
|
||||
|
||||
supportedAudioCodecs[container].push("opus")
|
||||
end if
|
||||
end for
|
||||
|
||||
' flac
|
||||
for each container in transContainers
|
||||
if di.CanDecodeAudio({ Codec: "flac", Container: container }).result
|
||||
if supportedAudioCodecs[container] = invalid
|
||||
supportedAudioCodecs[container] = []
|
||||
end if
|
||||
|
||||
supportedAudioCodecs[container].push("flac")
|
||||
end if
|
||||
end for
|
||||
|
||||
' vorbis
|
||||
for each container in transContainers
|
||||
if di.CanDecodeAudio({ Codec: "vorbis", Container: container }).result
|
||||
if supportedAudioCodecs[container] = invalid
|
||||
supportedAudioCodecs[container] = []
|
||||
end if
|
||||
|
||||
supportedAudioCodecs[container].push("vorbis")
|
||||
end if
|
||||
end for
|
||||
|
||||
' aac
|
||||
for each container in transContainers
|
||||
if di.CanDecodeAudio({ Codec: "aac", Container: container }).result
|
||||
if supportedAudioCodecs[container] = invalid
|
||||
supportedAudioCodecs[container] = []
|
||||
end if
|
||||
|
||||
supportedAudioCodecs[container].push("aac")
|
||||
end if
|
||||
end for
|
||||
|
||||
' mp3
|
||||
for each container in transContainers
|
||||
if di.CanDecodeAudio({ Codec: "mp3", Container: container }).result
|
||||
if supportedAudioCodecs[container] = invalid
|
||||
supportedAudioCodecs[container] = []
|
||||
end if
|
||||
|
||||
supportedAudioCodecs[container].push("mp3")
|
||||
end if
|
||||
end for
|
||||
|
||||
' HDR SUPPORT
|
||||
h264VideoRangeTypes = "SDR"
|
||||
hevcVideoRangeTypes = "SDR"
|
||||
vp9VideoRangeTypes = "SDR"
|
||||
av1VideoRangeTypes = "SDR"
|
||||
|
||||
dp = di.GetDisplayProperties()
|
||||
if dp.Hdr10 ' or dp.Hdr10Plus?
|
||||
if dp.Hdr10
|
||||
hevcVideoRangeTypes = hevcVideoRangeTypes + "|HDR10"
|
||||
vp9VideoRangeTypes = vp9VideoRangeTypes + "|HDR10"
|
||||
av1VideoRangeTypes = av1VideoRangeTypes + "|HDR10"
|
||||
end if
|
||||
if dp.Hdr10Plus
|
||||
av1VideoRangeTypes = av1VideoRangeTypes + "|HDR10+"
|
||||
end if
|
||||
if dp.HLG
|
||||
hevcVideoRangeTypes = hevcVideoRangeTypes + "|HLG"
|
||||
vp9VideoRangeTypes = vp9VideoRangeTypes + "|HLG"
|
||||
av1VideoRangeTypes = av1VideoRangeTypes + "|HLG"
|
||||
end if
|
||||
if dp.DolbyVision
|
||||
h264VideoRangeTypes = hevcVideoRangeTypes + "|DOVI"
|
||||
hevcVideoRangeTypes = hevcVideoRangeTypes + "|DOVI"
|
||||
'vp9VideoRangeTypes = vp9VideoRangeTypes + ",DOVI" no evidence that vp9 can hold DOVI
|
||||
av1VideoRangeTypes = av1VideoRangeTypes + "|DOVI"
|
||||
|
@ -318,18 +280,18 @@ function getDeviceProfile() as object
|
|||
"TranscodingProfiles": [],
|
||||
"ContainerProfiles": [],
|
||||
"CodecProfiles": [
|
||||
{
|
||||
"Type": "VideoAudio",
|
||||
"Codec": DirectPlayProfile[1].AudioCodec, ' Use supported MKV Audio list
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "AudioChannels",
|
||||
"Value": maxAudioChannels,
|
||||
"IsRequired": false
|
||||
}
|
||||
]
|
||||
}
|
||||
' {
|
||||
' "Type": "VideoAudio",
|
||||
' "Codec": DirectPlayProfile[1].AudioCodec, ' Use supported MKV Audio list
|
||||
' "Conditions": [
|
||||
' {
|
||||
' "Condition": "LessThanEqual",
|
||||
' "Property": "AudioChannels",
|
||||
' "Value": maxAudioChannels,
|
||||
' "IsRequired": false
|
||||
' }
|
||||
' ]
|
||||
' }
|
||||
],
|
||||
"SubtitleProfiles": [
|
||||
{
|
||||
|
@ -352,141 +314,173 @@ function getDeviceProfile() as object
|
|||
}
|
||||
|
||||
' build TranscodingProfiles
|
||||
' create an audio profile for each audio codec supported by the mp4 container
|
||||
for each supportedMp4AudioCodec in supportedAudioCodecs["mp4"]
|
||||
' streaming
|
||||
deviceProfile.TranscodingProfiles.push({
|
||||
"Container": supportedMp4AudioCodec,
|
||||
'
|
||||
for each audioCodec in mp4AudioCodecs.split(",")
|
||||
streamingArray = {
|
||||
"Container": audioCodec,
|
||||
"Type": "Audio",
|
||||
"AudioCodec": supportedMp4AudioCodec,
|
||||
"AudioCodec": audioCodec,
|
||||
"Context": "Streaming",
|
||||
"Protocol": "http",
|
||||
"MaxAudioChannels": maxAudioChannels
|
||||
})
|
||||
' static
|
||||
deviceProfile.TranscodingProfiles.push({
|
||||
"Container": supportedMp4AudioCodec,
|
||||
}
|
||||
staticArray = {
|
||||
"Container": audioCodec,
|
||||
"Type": "Audio",
|
||||
"AudioCodec": supportedMp4AudioCodec,
|
||||
"AudioCodec": audioCodec,
|
||||
"Context": "Static",
|
||||
"Protocol": "http",
|
||||
"MaxAudioChannels": maxAudioChannels
|
||||
})
|
||||
end for
|
||||
' create a video profile for each container in transContainers
|
||||
for each container in transContainers
|
||||
audioCodecs = []
|
||||
videoCodecs = []
|
||||
for each codec in supportedAudioCodecs[container]
|
||||
audioCodecs.push(codec)
|
||||
end for
|
||||
for each codec in supportedVideoCodecs[container]
|
||||
videoCodecs.push(codec)
|
||||
end for
|
||||
containerArray = {
|
||||
"Container": container,
|
||||
"Context": "Static",
|
||||
"Type": "Video",
|
||||
"AudioCodec": audioCodecs.join(","),
|
||||
"VideoCodec": videoCodecs.join(","),
|
||||
"MaxAudioChannels": maxAudioChannels
|
||||
}
|
||||
|
||||
if container = "ts"
|
||||
containerArray["Context"] = "Streaming"
|
||||
containerArray["Protocol"] = "hls"
|
||||
containerArray["MinSegments"] = "1"
|
||||
containerArray["BreakOnNonKeyFrames"] = true
|
||||
else if container = "mp4"
|
||||
containerArray["Context"] = "Static"
|
||||
containerArray["Protocol"] = "http"
|
||||
end if
|
||||
deviceProfile.TranscodingProfiles.push(containerArray)
|
||||
end for
|
||||
' use ts container for aac
|
||||
if audioCodec = "aac"
|
||||
if di.CanDecodeAudio({ Codec: audioCodec, Container: "ts", ChCnt: maxAudioChannels.trim().ToInt() }).result
|
||||
streamingArray["Container"] = "ts"
|
||||
staticArray["Container"] = "ts"
|
||||
|
||||
' build CodecProfiles
|
||||
if addH264Profile
|
||||
' determine highest level supported
|
||||
h264HighestLevel = 4.2
|
||||
h264HighestLevelSupported = 0.0
|
||||
for each container in transContainers
|
||||
for each profile in hevcProfiles
|
||||
for each level in supportedVideoCodecs[container]["h264"][profile]
|
||||
levelFloat = level.ToFloat()
|
||||
if levelFloat > h264HighestLevelSupported
|
||||
h264HighestLevelSupported = levelFloat
|
||||
end if
|
||||
if h264HighestLevelSupported = h264HighestLevel then exit for
|
||||
end for
|
||||
if h264HighestLevelSupported = h264HighestLevel then exit for
|
||||
end for
|
||||
if h264HighestLevelSupported = h264HighestLevel then exit for
|
||||
end for
|
||||
|
||||
h264LevelString = "41"
|
||||
if h264HighestLevelSupported = 4.2
|
||||
h264LevelString = "42"
|
||||
end if
|
||||
|
||||
|
||||
videoProfiles = []
|
||||
for each container in transContainers
|
||||
if supportedVideoCodecs[container]["h264"] <> invalid
|
||||
for each profile in supportedVideoCodecs[container]["h264"]
|
||||
videoProfiles.push(profile)
|
||||
end for
|
||||
exit for
|
||||
deviceProfile.TranscodingProfiles.push(streamingArray)
|
||||
deviceProfile.TranscodingProfiles.push(staticArray)
|
||||
end if
|
||||
else
|
||||
' use audioCodec as container for everything else
|
||||
if di.CanDecodeAudio({ Codec: audioCodec, Container: audioCodec, ChCnt: maxAudioChannels.trim().ToInt() }).result
|
||||
deviceProfile.TranscodingProfiles.push(streamingArray)
|
||||
deviceProfile.TranscodingProfiles.push(staticArray)
|
||||
end if
|
||||
end for
|
||||
|
||||
codecProfileArray = {
|
||||
"Type": "Video",
|
||||
"Codec": "h264",
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "NotEquals",
|
||||
"Property": "IsAnamorphic",
|
||||
"Value": "true",
|
||||
"IsRequired": false
|
||||
},
|
||||
{
|
||||
"Condition": "EqualsAny",
|
||||
"Property": "VideoProfile",
|
||||
"Value": videoProfiles.join("|"),
|
||||
"IsRequired": false
|
||||
},
|
||||
{
|
||||
"Condition": "EqualsAny",
|
||||
"Property": "VideoRangeType",
|
||||
"Value": "SDR",
|
||||
"IsRequired": false
|
||||
},
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "VideoLevel",
|
||||
"Value": h264LevelString,
|
||||
"IsRequired": false
|
||||
}
|
||||
]
|
||||
}
|
||||
bitRateArray = GetBitRateLimit("h264")
|
||||
if bitRateArray.count() > 0
|
||||
codecProfileArray.Conditions.push(bitRateArray)
|
||||
end if
|
||||
deviceProfile.CodecProfiles.push(codecProfileArray)
|
||||
end for
|
||||
|
||||
|
||||
tsArray = {
|
||||
"Container": "ts",
|
||||
"Context": "Streaming",
|
||||
"Protocol": "hls",
|
||||
"Type": "Video",
|
||||
"AudioCodec": tsAudioCodecs,
|
||||
"VideoCodec": tsVideoCodecs,
|
||||
"MaxAudioChannels": maxAudioChannels,
|
||||
"MinSegments": 1,
|
||||
"BreakOnNonKeyFrames": false
|
||||
}
|
||||
mp4Array = {
|
||||
"Container": "mp4",
|
||||
"Context": "Streaming",
|
||||
"Protocol": "hls",
|
||||
"Type": "Video",
|
||||
"AudioCodec": mp4AudioCodecs,
|
||||
"VideoCodec": mp4VideoCodecs,
|
||||
"MaxAudioChannels": maxAudioChannels,
|
||||
"MinSegments": 1,
|
||||
"BreakOnNonKeyFrames": false
|
||||
}
|
||||
|
||||
' surround sound
|
||||
' move preferred surround sound codec to front of string
|
||||
if maxAudioChannels.ToInt() > 2
|
||||
' search codec strings for our preferred codec
|
||||
tsCodecStringPosition = tsArray.AudioCodec.Instr(0, "," + surroundSoundCodec)
|
||||
mp4CodecStringPosition = mp4Array.AudioCodec.Instr(0, "," + surroundSoundCodec)
|
||||
|
||||
if tsCodecStringPosition <> -1
|
||||
' ts supports our prefered codec
|
||||
' remove codec from string
|
||||
tsArray.AudioCodec.Replace("," + surroundSoundCodec, "")
|
||||
' put codec in front of string
|
||||
tsArray.AudioCodec = surroundSoundCodec + "," + tsArray.AudioCodec
|
||||
end if
|
||||
if mp4CodecStringPosition <> -1
|
||||
' mp4 supports our prefered codec
|
||||
' remove codec from string
|
||||
mp4Array.AudioCodec.Replace("," + surroundSoundCodec, "")
|
||||
' put codec in front of string
|
||||
mp4Array.AudioCodec = surroundSoundCodec + "," + mp4Array.AudioCodec
|
||||
end if
|
||||
end if
|
||||
|
||||
if addMpeg2Profile
|
||||
mpeg2Levels = []
|
||||
for each container in transContainers
|
||||
if supportedVideoCodecs[container] <> invalid
|
||||
if supportedVideoCodecs[container]["mpeg2"] <> invalid
|
||||
for each level in supportedVideoCodecs[container]["mpeg2"]
|
||||
mpeg2Levels.push(level)
|
||||
end for
|
||||
if mpeg2Levels.count() > 0 then exit for
|
||||
deviceProfile.TranscodingProfiles.push(tsArray)
|
||||
deviceProfile.TranscodingProfiles.push(mp4Array)
|
||||
|
||||
' Build CodecProfiles
|
||||
'
|
||||
' H264
|
||||
h264Mp4LevelSupported = 0.0
|
||||
h264TsLevelSupported = 0.0
|
||||
h264AssProfiles = {}
|
||||
h264LevelString = invalid
|
||||
for each container in profileSupport
|
||||
for each profile in profileSupport[container]["h264"]
|
||||
h264AssProfiles.AddReplace(profile, true)
|
||||
for each level in profileSupport[container]["h264"][profile]
|
||||
levelFloat = level.ToFloat()
|
||||
if container = "mp4"
|
||||
if levelFloat > h264Mp4LevelSupported
|
||||
h264Mp4LevelSupported = levelFloat
|
||||
end if
|
||||
else if container = "ts"
|
||||
if levelFloat > h264TsLevelSupported
|
||||
h264TsLevelSupported = levelFloat
|
||||
end if
|
||||
end if
|
||||
end if
|
||||
end for
|
||||
end for
|
||||
end for
|
||||
|
||||
h264LevelString = h264Mp4LevelSupported
|
||||
if h264TsLevelSupported > h264Mp4LevelSupported
|
||||
h264LevelString = h264TsLevelSupported
|
||||
end if
|
||||
' convert to string
|
||||
h264LevelString = h264LevelString.ToStr()
|
||||
' remove decimals
|
||||
h264LevelString = removeDecimals(h264LevelString)
|
||||
|
||||
|
||||
codecProfileArray = {
|
||||
"Type": "Video",
|
||||
"Codec": "h264",
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "NotEquals",
|
||||
"Property": "IsAnamorphic",
|
||||
"Value": "true",
|
||||
"IsRequired": false
|
||||
},
|
||||
{
|
||||
"Condition": "EqualsAny",
|
||||
"Property": "VideoProfile",
|
||||
"Value": h264AssProfiles.Keys().join("|"),
|
||||
"IsRequired": false
|
||||
},
|
||||
{
|
||||
"Condition": "EqualsAny",
|
||||
"Property": "VideoRangeType",
|
||||
"Value": h264VideoRangeTypes,
|
||||
"IsRequired": false
|
||||
},
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "VideoLevel",
|
||||
"Value": h264LevelString,
|
||||
"IsRequired": false
|
||||
}
|
||||
]
|
||||
}
|
||||
bitRateArray = GetBitRateLimit("h264")
|
||||
if bitRateArray.count() > 0
|
||||
codecProfileArray.Conditions.push(bitRateArray)
|
||||
end if
|
||||
deviceProfile.CodecProfiles.push(codecProfileArray)
|
||||
|
||||
' MPEG2
|
||||
if addMpeg2
|
||||
mpeg2Levels = []
|
||||
for each container in profileSupport
|
||||
for each level in profileSupport[container]["mpeg2"]
|
||||
if mpeg2Levels[level] = invalid
|
||||
mpeg2Levels.push(level)
|
||||
end if
|
||||
end for
|
||||
end for
|
||||
|
||||
codecProfileArray = {
|
||||
|
@ -508,33 +502,35 @@ function getDeviceProfile() as object
|
|||
deviceProfile.CodecProfiles.push(codecProfileArray)
|
||||
end if
|
||||
|
||||
if addAv1Profile
|
||||
' determine highest level supported
|
||||
av1HighestLevel = 5.1
|
||||
av1HighestLevelSupported = 0.0
|
||||
for each container in transContainers
|
||||
for each profile in hevcProfiles
|
||||
for each level in supportedVideoCodecs[container]["av1"][profile]
|
||||
if addAv1
|
||||
av1Mp4LevelSupported = 0.0
|
||||
av1TsLevelSupported = 0.0
|
||||
av1AssProfiles = []
|
||||
av1HighestLevel = 0.0
|
||||
for each container in profileSupport
|
||||
for each profile in profileSupport[container]["av1"]
|
||||
av1AssProfiles.AddReplace(profile, true)
|
||||
for each level in profileSupport[container]["av1"][profile]
|
||||
levelFloat = level.ToFloat()
|
||||
if levelFloat > av1HighestLevelSupported
|
||||
av1HighestLevelSupported = levelFloat
|
||||
if container = "mp4"
|
||||
if levelFloat > av1Mp4LevelSupported
|
||||
av1Mp4LevelSupported = levelFloat
|
||||
end if
|
||||
else if container = "ts"
|
||||
if levelFloat > av1TsLevelSupported
|
||||
av1TsLevelSupported = levelFloat
|
||||
end if
|
||||
end if
|
||||
if av1HighestLevelSupported = av1HighestLevel then exit for
|
||||
end for
|
||||
if av1HighestLevelSupported = av1HighestLevel then exit for
|
||||
end for
|
||||
if av1HighestLevelSupported = av1HighestLevel then exit for
|
||||
end for
|
||||
|
||||
videoProfiles = []
|
||||
for each container in transContainers
|
||||
if supportedVideoCodecs[container]["av1"] <> invalid
|
||||
for each profile in supportedVideoCodecs[container]["av1"]
|
||||
videoProfiles.push(profile)
|
||||
end for
|
||||
exit for
|
||||
end if
|
||||
end for
|
||||
av1HighestLevel = av1Mp4LevelSupported
|
||||
if av1TsLevelSupported > av1Mp4LevelSupported
|
||||
av1HighestLevel = av1TsLevelSupported
|
||||
end if
|
||||
|
||||
|
||||
|
||||
codecProfileArray = {
|
||||
"Type": "Video",
|
||||
|
@ -543,7 +539,7 @@ function getDeviceProfile() as object
|
|||
{
|
||||
"Condition": "EqualsAny",
|
||||
"Property": "VideoProfile",
|
||||
"Value": videoProfiles.join("|"),
|
||||
"Value": av1AssProfiles.Keys().join("|"),
|
||||
"IsRequired": false
|
||||
},
|
||||
{
|
||||
|
@ -555,7 +551,7 @@ function getDeviceProfile() as object
|
|||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "VideoLevel",
|
||||
"Value": (120 * av1HighestLevelSupported).ToStr(),
|
||||
"Value": (120 * av1HighestLevel).ToStr(),
|
||||
"IsRequired": false
|
||||
}
|
||||
]
|
||||
|
@ -567,38 +563,38 @@ function getDeviceProfile() as object
|
|||
deviceProfile.CodecProfiles.push(codecProfileArray)
|
||||
end if
|
||||
|
||||
if addHevcProfile
|
||||
' determine highest level supported
|
||||
hevcHighestLevel = 5.1
|
||||
hevcHighestLevelSupported = 0.0
|
||||
for each container in transContainers
|
||||
for each profile in hevcProfiles
|
||||
for each level in supportedVideoCodecs[container]["hevc"][profile]
|
||||
if addHevc
|
||||
hevcMp4LevelSupported = 0.0
|
||||
hevcTsLevelSupported = 0.0
|
||||
hevcAssProfiles = {}
|
||||
hevcHighestLevel = 0.0
|
||||
for each container in profileSupport
|
||||
for each profile in profileSupport[container]["hevc"]
|
||||
hevcAssProfiles.AddReplace(profile, true)
|
||||
for each level in profileSupport[container]["hevc"][profile]
|
||||
levelFloat = level.ToFloat()
|
||||
if levelFloat > hevcHighestLevelSupported
|
||||
hevcHighestLevelSupported = levelFloat
|
||||
if container = "mp4"
|
||||
if levelFloat > hevcMp4LevelSupported
|
||||
hevcMp4LevelSupported = levelFloat
|
||||
end if
|
||||
else if container = "ts"
|
||||
if levelFloat > hevcTsLevelSupported
|
||||
hevcTsLevelSupported = levelFloat
|
||||
end if
|
||||
end if
|
||||
if hevcHighestLevelSupported = hevcHighestLevel then exit for
|
||||
end for
|
||||
if hevcHighestLevelSupported = hevcHighestLevel then exit for
|
||||
end for
|
||||
if hevcHighestLevelSupported = hevcHighestLevel then exit for
|
||||
end for
|
||||
|
||||
hevcLevelString = "120"
|
||||
if hevcHighestLevelSupported = 5.1
|
||||
hevcLevelString = "153"
|
||||
hevcHighestLevel = hevcMp4LevelSupported
|
||||
if hevcTsLevelSupported > hevcMp4LevelSupported
|
||||
hevcHighestLevel = hevcTsLevelSupported
|
||||
end if
|
||||
|
||||
videoProfiles = []
|
||||
for each container in transContainers
|
||||
if supportedVideoCodecs[container]["hevc"] <> invalid
|
||||
for each profile in supportedVideoCodecs[container]["hevc"]
|
||||
videoProfiles.push(profile)
|
||||
end for
|
||||
exit for
|
||||
end if
|
||||
end for
|
||||
hevcLevelString = "120"
|
||||
if hevcHighestLevel = 5.1
|
||||
hevcLevelString = "153"
|
||||
end if
|
||||
|
||||
codecProfileArray = {
|
||||
"Type": "Video",
|
||||
|
@ -613,7 +609,7 @@ function getDeviceProfile() as object
|
|||
{
|
||||
"Condition": "EqualsAny",
|
||||
"Property": "VideoProfile",
|
||||
"Value": videoProfiles.join("|"),
|
||||
"Value": profileSupport["ts"]["hevc"].Keys().join("|"),
|
||||
"IsRequired": false
|
||||
},
|
||||
{
|
||||
|
@ -630,6 +626,7 @@ function getDeviceProfile() as object
|
|||
}
|
||||
]
|
||||
}
|
||||
|
||||
bitRateArray = GetBitRateLimit("h265")
|
||||
if bitRateArray.count() > 0
|
||||
codecProfileArray.Conditions.push(bitRateArray)
|
||||
|
@ -637,15 +634,14 @@ function getDeviceProfile() as object
|
|||
deviceProfile.CodecProfiles.push(codecProfileArray)
|
||||
end if
|
||||
|
||||
if addVp9Profile
|
||||
videoProfiles = []
|
||||
for each container in transContainers
|
||||
if supportedVideoCodecs[container]["vp9"] <> invalid
|
||||
for each profile in supportedVideoCodecs[container]["vp9"]
|
||||
videoProfiles.push(profile)
|
||||
end for
|
||||
exit for
|
||||
end if
|
||||
if addVp9
|
||||
vp9Profiles = []
|
||||
for each container in profileSupport
|
||||
for each profile in profileSupport[container]["vp9"]
|
||||
if vp9Profiles[profile] = invalid
|
||||
vp9Profiles.push(profile)
|
||||
end if
|
||||
end for
|
||||
end for
|
||||
|
||||
codecProfileArray = {
|
||||
|
@ -654,8 +650,8 @@ function getDeviceProfile() as object
|
|||
"Conditions": [
|
||||
{
|
||||
"Condition": "EqualsAny",
|
||||
"Property": "VideoProfile",
|
||||
"Value": videoProfiles.join("|"),
|
||||
"Property": "VideoLevel",
|
||||
"Value": vp9Profiles.join("|"),
|
||||
"IsRequired": false
|
||||
},
|
||||
{
|
||||
|
@ -666,6 +662,7 @@ function getDeviceProfile() as object
|
|||
}
|
||||
]
|
||||
}
|
||||
|
||||
bitRateArray = GetBitRateLimit("vp9")
|
||||
if bitRateArray.count() > 0
|
||||
codecProfileArray.Conditions.push(bitRateArray)
|
||||
|
@ -834,3 +831,35 @@ function GetBitRateLimit(codec as string) as object
|
|||
end if
|
||||
return {}
|
||||
end function
|
||||
|
||||
' Recieves and returns an assArray of supported profiles and levels for each video codec
|
||||
function updateProfileArray(profileArray as object, videoCodec as string, videoProfile as string, profileLevel = "" as string) as object
|
||||
' validate params
|
||||
if profileArray = invalid then return {}
|
||||
if videoCodec = "" or videoProfile = "" then return profileArray
|
||||
|
||||
if profileArray[videoCodec] = invalid
|
||||
profileArray[videoCodec] = {}
|
||||
end if
|
||||
|
||||
if profileArray[videoCodec][videoProfile] = invalid
|
||||
profileArray[videoCodec][videoProfile] = {}
|
||||
end if
|
||||
|
||||
' add profileLevel if a value was provided
|
||||
if profileLevel <> ""
|
||||
if profileArray[videoCodec][videoProfile][profileLevel] = invalid
|
||||
profileArray[videoCodec][videoProfile].AddReplace(profileLevel, true)
|
||||
end if
|
||||
end if
|
||||
|
||||
' profileSupport[container][codec][profile][level]
|
||||
return profileArray
|
||||
end function
|
||||
|
||||
' Remove all decimals from a string
|
||||
function removeDecimals(value as string) as string
|
||||
r = CreateObject("roRegex", "\.", "")
|
||||
value = r.ReplaceAll(value, "")
|
||||
return value
|
||||
end function
|
||||
|
|
Loading…
Reference in New Issue
Block a user