mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2024-12-25 10:16:11 +00:00
more optimizations to new playback code
add experimental setting to enable playback with new method
This commit is contained in:
parent
33ba485b0b
commit
dcb7fd42fa
2 changed files with 60 additions and 36 deletions
|
@ -37,33 +37,40 @@ class PlayUtils():
|
||||||
'''
|
'''
|
||||||
New style to retrieve the best playback method based on sending the profile to the server
|
New style to retrieve the best playback method based on sending the profile to the server
|
||||||
Based on capabilities the correct path is returned, including livestreams that need to be opened by the server
|
Based on capabilities the correct path is returned, including livestreams that need to be opened by the server
|
||||||
TODO: Close livestream if needed (RequiresClosing in livestream source)
|
|
||||||
'''
|
'''
|
||||||
playurl = None
|
playurl = None
|
||||||
pbinfo = self.getPlaybackInfo()
|
pbinfo = self.getPlaybackInfo()
|
||||||
if pbinfo:
|
if pbinfo:
|
||||||
xbmc.log("getPlayUrl pbinfo: %s" %(pbinfo))
|
xbmc.log("getPlayUrl pbinfo: %s" %(pbinfo))#debug
|
||||||
|
|
||||||
if pbinfo["Protocol"] == "SupportsDirectPlay":
|
if pbinfo["SupportsDirectPlay"]:
|
||||||
playmethod = "DirectPlay"
|
playmethod = "DirectPlay"
|
||||||
elif pbinfo["Protocol"] == "SupportsDirectStream":
|
playurl = pbinfo["Path"]
|
||||||
|
|
||||||
|
elif pbinfo["SupportsDirectStream"]:
|
||||||
playmethod = "DirectStream"
|
playmethod = "DirectStream"
|
||||||
elif pbinfo.get('LiveStreamId'):
|
playurl = self.directStream()
|
||||||
playmethod = "LiveStream"
|
|
||||||
else:
|
else:
|
||||||
playmethod = "Transcode"
|
playmethod = "Transcode"
|
||||||
|
if pbinfo.get("TranscodingUrl"):
|
||||||
|
playurl = self.server + pbinfo["TranscodingUrl"]
|
||||||
|
else:
|
||||||
|
playurl = self.transcoding()
|
||||||
|
|
||||||
playurl = pbinfo["Path"]
|
xbmc.log("getPlayUrl playmethod: %s - playurl: %s" %(playmethod, playurl))#debug
|
||||||
xbmc.log("getPlayUrl playmethod: %s - playurl: %s" %(playmethod, playurl))
|
|
||||||
window('emby_%s.playmethod' % playurl, value=playmethod)
|
window('emby_%s.playmethod' % playurl, value=playmethod)
|
||||||
if pbinfo["RequiresClosing"] and pbinfo.get('LiveStreamId'):
|
if pbinfo["RequiresClosing"] and pbinfo.get('LiveStreamId'):
|
||||||
window('emby_%s.livestreamid' % playurl, value=pbinfo["LiveStreamId"])
|
window('emby_%s.livestreamid' % playurl, value=pbinfo["LiveStreamId"])
|
||||||
|
|
||||||
return playurl
|
return playurl
|
||||||
|
|
||||||
|
|
||||||
def getPlayUrl(self):
|
def getPlayUrl(self):
|
||||||
|
|
||||||
|
#TEMP !
|
||||||
|
if settings('experimentalPlayback') == "true":
|
||||||
|
return self.getPlayUrlNew()
|
||||||
|
|
||||||
playurl = None
|
playurl = None
|
||||||
|
|
||||||
if (self.item.get('Type') in ("Recording", "TvChannel") and self.item.get('MediaSources')
|
if (self.item.get('Type') in ("Recording", "TvChannel") and self.item.get('MediaSources')
|
||||||
|
@ -455,37 +462,51 @@ class PlayUtils():
|
||||||
"LiveStreamId": None
|
"LiveStreamId": None
|
||||||
}
|
}
|
||||||
pbinfo = self.doUtils(url, postBody=body, action_type="POST")
|
pbinfo = self.doUtils(url, postBody=body, action_type="POST")
|
||||||
xbmc.log("getPlaybackInfo: %s" %pbinfo)
|
xbmc.log("getPlaybackInfo: %s" %pbinfo)#debug
|
||||||
mediaSource = self.getOptimalMediaSource(pbinfo["MediaSources"])
|
mediaSource = self.getOptimalMediaSource(pbinfo["MediaSources"])
|
||||||
if mediaSource and mediaSource["RequiresOpening"]:
|
if mediaSource and mediaSource["RequiresOpening"]:
|
||||||
mediaSource = self.getLiveStream(pbinfo["PlaySessionId"], mediaSource)
|
mediaSource = self.getLiveStream(pbinfo["PlaySessionId"], mediaSource)
|
||||||
|
|
||||||
|
|
||||||
return mediaSource
|
return mediaSource
|
||||||
|
|
||||||
def getOptimalMediaSource(self, mediasources):
|
def getOptimalMediaSource(self, mediasources):
|
||||||
'''
|
'''
|
||||||
Select the best possible mediasource for playback
|
Select the best possible mediasource for playback
|
||||||
Because we posted our deviceprofile to the server,
|
We select the best stream based on a score
|
||||||
only streams will be returned that can actually be played by this client so no need to check bitrates etc.
|
TODO: Incorporate user preferences for best stream selection
|
||||||
'''
|
'''
|
||||||
preferredStreamOrder = ["SupportsDirectPlay","SupportsDirectStream","SupportsTranscoding"]
|
|
||||||
bestSource = {}
|
bestSource = {}
|
||||||
for prefstream in preferredStreamOrder:
|
lastScore = 0
|
||||||
for source in mediasources:
|
for mediasource in mediasources:
|
||||||
if source[prefstream] == True:
|
score = 0
|
||||||
if prefstream == "SupportsDirectPlay":
|
#transform filepath to kodi compliant
|
||||||
#always prefer direct play
|
if mediasource["Protocol"] == "File":
|
||||||
alt_playurl = self.checkDirectPlayPath(source["Path"])
|
mediasource["Path"] = self.transformFilePath(mediasource["Path"])
|
||||||
if alt_playurl:
|
|
||||||
bestSource = source
|
#The bitrate and video dimension is an important quality argument so also base our score on that
|
||||||
source["Path"] = alt_playurl
|
score += mediasource.get("Bitrate",0)
|
||||||
elif bestSource.get("BitRate",0) < source.get("Bitrate",0):
|
for stream in mediasource["MediaStreams"]:
|
||||||
#prefer stream with highest bitrate for http sources
|
if stream["Type"] == "Video" and stream.get("Width"):
|
||||||
bestSource = source
|
#some streams report high bitrate but have no video width so stream with video width has highest score
|
||||||
elif not source.get("Bitrate") and source.get("RequiresOpening"):
|
#this is especially true for videos in channels, like trailers
|
||||||
#livestream
|
score += stream["Width"] * 10000
|
||||||
bestSource = source
|
|
||||||
xbmc.log("getOptimalMediaSource: %s" %bestSource)
|
#directplay has the highest score
|
||||||
|
if mediasource["SupportsDirectPlay"] and self.supportsDirectPlay(mediasource):
|
||||||
|
score += 100000000
|
||||||
|
|
||||||
|
#directstream also scores well, the transcode option has no points as its a last resort
|
||||||
|
if mediasource["SupportsDirectStream"]:
|
||||||
|
score += 5000000
|
||||||
|
|
||||||
|
#TODO: If our user has any specific preferences we can alter the score
|
||||||
|
# For now we just select the highest quality as our prefered score
|
||||||
|
if score >= lastScore:
|
||||||
|
lastScore = score
|
||||||
|
bestSource = mediasource
|
||||||
|
|
||||||
|
xbmc.log("getOptimalMediaSource: %s" %bestSource)#debug
|
||||||
return bestSource
|
return bestSource
|
||||||
|
|
||||||
def getLiveStream(self, playSessionId, mediaSource):
|
def getLiveStream(self, playSessionId, mediaSource):
|
||||||
|
@ -501,11 +522,12 @@ class PlayUtils():
|
||||||
"SubtitleStreamIndex": None #TODO
|
"SubtitleStreamIndex": None #TODO
|
||||||
}
|
}
|
||||||
streaminfo = self.doUtils(url, postBody=body, action_type="POST")
|
streaminfo = self.doUtils(url, postBody=body, action_type="POST")
|
||||||
xbmc.log("getLiveStream: %s" %streaminfo)
|
xbmc.log("getLiveStream: %s" %streaminfo)#debug
|
||||||
|
streaminfo["MediaSource"]["SupportsDirectPlay"] = self.supportsDirectPlay(streaminfo["MediaSource"])
|
||||||
return streaminfo["MediaSource"]
|
return streaminfo["MediaSource"]
|
||||||
|
|
||||||
def checkDirectPlayPath(self, playurl):
|
def transformFilePath(self, playurl):
|
||||||
|
#Transform filepath to Kodi compatible path
|
||||||
if self.item.get('VideoType'):
|
if self.item.get('VideoType'):
|
||||||
# Specific format modification
|
# Specific format modification
|
||||||
if self.item['VideoType'] == "Dvd":
|
if self.item['VideoType'] == "Dvd":
|
||||||
|
@ -518,10 +540,11 @@ class PlayUtils():
|
||||||
playurl = playurl.replace("\\\\", "smb://")
|
playurl = playurl.replace("\\\\", "smb://")
|
||||||
playurl = playurl.replace("\\", "/")
|
playurl = playurl.replace("\\", "/")
|
||||||
|
|
||||||
if xbmcvfs.exists(playurl):
|
|
||||||
return playurl
|
return playurl
|
||||||
else:
|
|
||||||
return None
|
def supportsDirectPlay(self, mediasource):
|
||||||
|
#Figure out if the path can be directly played as the bool returned from the server response is not 100% reliable
|
||||||
|
return xbmcvfs.exists(mediasource["Path"])
|
||||||
|
|
||||||
def getDeviceProfile(self):
|
def getDeviceProfile(self):
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -81,5 +81,6 @@
|
||||||
<setting label="30535" type="action" action="RunPlugin(plugin://plugin.video.emby?mode=deviceid)" />
|
<setting label="30535" type="action" action="RunPlugin(plugin://plugin.video.emby?mode=deviceid)" />
|
||||||
<setting label="33093" type="folder" id="backupPath" option="writeable" />
|
<setting label="33093" type="folder" id="backupPath" option="writeable" />
|
||||||
<setting label="33092" type="action" action="RunPlugin(plugin://plugin.video.emby?mode=backup)" visible="!eq(-1,)" option="close" />
|
<setting label="33092" type="action" action="RunPlugin(plugin://plugin.video.emby?mode=backup)" visible="!eq(-1,)" option="close" />
|
||||||
|
<setting id="experimentalPlayback" type="bool" label="Enable new experimental playback" default="false" />
|
||||||
</category>
|
</category>
|
||||||
</settings>
|
</settings>
|
||||||
|
|
Loading…
Reference in a new issue