more optimizations to new playback code

add experimental setting to enable playback with new method
This commit is contained in:
marcelveldt 2016-09-29 20:49:35 +02:00
parent 33ba485b0b
commit dcb7fd42fa
2 changed files with 60 additions and 36 deletions

View File

@ -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 {

View File

@ -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>