| 
					
				 | 
			
			
				@@ -407,8 +407,13 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (mediaSource.SupportsDirectPlay) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (mediaSource.IsRemote && forceDirectPlayRemoteMediaSource) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (mediaSource.IsRemote && forceDirectPlayRemoteMediaSource && user.Policy.ForceRemoteSourceTranscoding) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    mediaSource.SupportsDirectPlay = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                else if (mediaSource.IsRemote && user.Policy.ForceRemoteSourceTranscoding) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                     mediaSource.SupportsDirectPlay = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -455,74 +460,112 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (mediaSource.SupportsDirectStream) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                options.MaxBitrate = GetMaxBitrate(maxBitrate, user); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (item is Audio) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if (!user.Policy.EnableAudioPlaybackTranscoding) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        options.ForceDirectStream = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                else if (item is Video) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (mediaSource.IsRemote && forceDirectPlayRemoteMediaSource && user.Policy.ForceRemoteSourceTranscoding) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if (!user.Policy.EnableAudioPlaybackTranscoding && !user.Policy.EnableVideoPlaybackTranscoding && !user.Policy.EnablePlaybackRemuxing) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        options.ForceDirectStream = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    mediaSource.SupportsDirectStream = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                // The MediaSource supports direct stream, now test to see if the client supports it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    streamBuilder.BuildAudioItem(options) : 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    streamBuilder.BuildVideoItem(options); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (streamInfo == null || !streamInfo.IsDirectStream) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                else if (mediaSource.IsRemote && user.Policy.ForceRemoteSourceTranscoding) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     mediaSource.SupportsDirectStream = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (streamInfo != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    options.MaxBitrate = GetMaxBitrate(maxBitrate, user); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (item is Audio) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (!user.Policy.EnableAudioPlaybackTranscoding) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            options.ForceDirectStream = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    else if (item is Video) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (!user.Policy.EnableAudioPlaybackTranscoding && !user.Policy.EnableVideoPlaybackTranscoding && !user.Policy.EnablePlaybackRemuxing) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            options.ForceDirectStream = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // The MediaSource supports direct stream, now test to see if the client supports it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        streamBuilder.BuildAudioItem(options) : 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        streamBuilder.BuildVideoItem(options); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (streamInfo == null || !streamInfo.IsDirectStream) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        mediaSource.SupportsDirectStream = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (streamInfo != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (mediaSource.SupportsTranscoding) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                options.MaxBitrate = GetMaxBitrate(maxBitrate, user); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (mediaSource.IsRemote && user.Policy.ForceRemoteSourceTranscoding) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					if (GetMaxBitrate(maxBitrate, user) < mediaSource.Bitrate) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						options.MaxBitrate = GetMaxBitrate(maxBitrate, user); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						options.MaxBitrate = mediaSource.Bitrate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					options.MaxBitrate = GetMaxBitrate(maxBitrate, user); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 // The MediaSource supports direct stream, now test to see if the client supports it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     streamBuilder.BuildAudioItem(options) : 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     streamBuilder.BuildVideoItem(options); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (streamInfo != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    streamInfo.PlaySessionId = playSessionId; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if (streamInfo.PlayMethod == PlayMethod.Transcode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (mediaSource.IsRemote && user.Policy.ForceRemoteSourceTranscoding) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (streamInfo != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        streamInfo.PlaySessionId = playSessionId;                         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         streamInfo.StartPositionTicks = startTimeTicks; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        if (!allowVideoStreamCopy) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        if (!allowAudioStreamCopy) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         mediaSource.TranscodingContainer = streamInfo.Container; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         mediaSource.TranscodingSubProtocol = streamInfo.SubProtocol; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        // Do this after the above so that StartPositionTicks is set 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    }				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (streamInfo != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        streamInfo.PlaySessionId = playSessionId; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (streamInfo.PlayMethod == PlayMethod.Transcode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            streamInfo.StartPositionTicks = startTimeTicks; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            if (!allowVideoStreamCopy) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            if (!allowAudioStreamCopy) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            mediaSource.TranscodingContainer = streamInfo.Container; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            mediaSource.TranscodingSubProtocol = streamInfo.SubProtocol; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        // Do this after the above so that StartPositionTicks is set 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    // Do this after the above so that StartPositionTicks is set 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         private long? GetMaxBitrate(long? clientMaxBitrate, User user) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 |