| 
					
				 | 
			
			
				@@ -1,12 +1,10 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 using MediaBrowser.Common.Extensions; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 using MediaBrowser.Common.IO; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-using MediaBrowser.Controller.Channels; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 using MediaBrowser.Controller.Configuration; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 using MediaBrowser.Controller.Devices; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 using MediaBrowser.Controller.Dlna; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 using MediaBrowser.Controller.Entities; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 using MediaBrowser.Controller.Library; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-using MediaBrowser.Controller.LiveTv; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 using MediaBrowser.Controller.MediaEncoding; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 using MediaBrowser.Model.Configuration; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 using MediaBrowser.Model.Dlna; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -65,7 +63,6 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         protected IFileSystem FileSystem { get; private set; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        protected ILiveTvManager LiveTvManager { get; private set; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         protected IDlnaManager DlnaManager { get; private set; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         protected IDeviceManager DeviceManager { get; private set; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         protected ISubtitleEncoder SubtitleEncoder { get; private set; } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -75,14 +72,13 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// Initializes a new instance of the <see cref="BaseStreamingService" /> class. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// </summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             ZipClient = zipClient; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             MediaSourceManager = mediaSourceManager; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             DeviceManager = deviceManager; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             SubtitleEncoder = subtitleEncoder; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             DlnaManager = dlnaManager; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            LiveTvManager = liveTvManager; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             FileSystem = fileSystem; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             ServerConfigurationManager = serverConfig; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             UserManager = userManager; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -95,11 +91,10 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// Gets the command line arguments. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// </summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <param name="outputPath">The output path.</param> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        /// <param name="transcodingJobId">The transcoding job identifier.</param> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <param name="state">The state.</param> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <param name="isEncoding">if set to <c>true</c> [is encoding].</param> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <returns>System.String.</returns> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        protected abstract string GetCommandLineArguments(string outputPath, string transcodingJobId, StreamState state, bool isEncoding); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        protected abstract string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// Gets the type of the transcoding job. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -128,10 +123,10 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var outputFileExtension = GetOutputFileExtension(state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            var data = GetCommandLineArguments("dummy\\dummy", "dummyTranscodingId", state, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var data = GetCommandLineArguments("dummy\\dummy", state, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             data += "-" + (state.Request.DeviceId ?? string.Empty); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            data += "-" + (state.Request.StreamId ?? string.Empty); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            data += "-" + (state.Request.PlaySessionId ?? string.Empty); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             data += "-" + (state.Request.ClientTime ?? string.Empty); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var dataHash = data.GetMD5().ToString("N"); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -704,7 +699,7 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (!string.IsNullOrEmpty(state.SubtitleStream.Language)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath, state.MediaSource.Protocol, CancellationToken.None).Result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     if (!string.IsNullOrEmpty(charenc)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -719,8 +714,10 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     seconds.ToString(UsCulture)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var mediaPath = state.MediaPath ?? string.Empty; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return string.Format("subtitles='{0}:si={1}',setpts=PTS -{2}/TB", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.MediaPath.Replace('\\', '/').Replace(":/", "\\:/"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                mediaPath.Replace('\\', '/').Replace(":/", "\\:/"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 state.InternalSubtitleStreamOffset.ToString(UsCulture), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 seconds.ToString(UsCulture)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -895,12 +892,11 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// Gets the input argument. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// </summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        /// <param name="transcodingJobId">The transcoding job identifier.</param> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <param name="state">The state.</param> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <returns>System.String.</returns> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        protected string GetInputArgument(string transcodingJobId, StreamState state) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        protected string GetInputArgument(StreamState state) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            var arg = "-i " + GetInputPathArgument(transcodingJobId, state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var arg = "-i " + GetInputPathArgument(state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (state.SubtitleStream != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -913,27 +909,18 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return arg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        private string GetInputPathArgument(string transcodingJobId, StreamState state) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        private string GetInputPathArgument(StreamState state) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //if (state.InputProtocol == MediaProtocol.File && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //   state.RunTimeTicks.HasValue && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //   state.VideoType == VideoType.VideoFile && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //   !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //    if (state.RunTimeTicks.Value >= TimeSpan.FromMinutes(5).Ticks && state.IsInputVideo) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var protocol = state.InputProtocol; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var mediaPath = state.MediaPath ?? string.Empty; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            var inputPath = new[] { state.MediaPath }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var inputPath = new[] { mediaPath }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (state.IsInputVideo) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (!(state.VideoType == VideoType.Iso && state.IsoMount == null)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    inputPath = MediaEncoderHelpers.GetInputArgument(state.MediaPath, state.InputProtocol, state.IsoMount, state.PlayableStreamFileNames); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    inputPath = MediaEncoderHelpers.GetInputArgument(mediaPath, state.InputProtocol, state.IsoMount, state.PlayableStreamFileNames); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -947,55 +934,25 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 state.IsoMount = await IsoManager.Mount(state.MediaPath, cancellationTokenSource.Token).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (string.IsNullOrEmpty(state.MediaPath)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (state.MediaSource.RequiresOpening) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                var checkCodecs = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (string.Equals(state.ItemType, typeof(LiveTvChannel).Name)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var liveStreamResponse = await MediaSourceManager.OpenLiveStream(new LiveStreamRequest 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    var streamInfo = await LiveTvManager.GetChannelStream(state.Request.Id, cancellationTokenSource.Token).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.LiveTvStreamId = streamInfo.Id; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    OpenToken = state.MediaSource.OpenToken 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.MediaPath = streamInfo.Path; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.InputProtocol = streamInfo.Protocol; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                }, false, cancellationTokenSource.Token).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    await Task.Delay(1500, cancellationTokenSource.Token).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    AttachMediaStreamInfo(state, streamInfo, state.VideoRequest, state.RequestedUrl); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    checkCodecs = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                AttachMediaSourceInfo(state, liveStreamResponse.MediaSource, state.VideoRequest, state.RequestedUrl); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                else if (string.Equals(state.ItemType, typeof(LiveTvVideoRecording).Name) || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    string.Equals(state.ItemType, typeof(LiveTvAudioRecording).Name)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (state.VideoRequest != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    var streamInfo = await LiveTvManager.GetRecordingStream(state.Request.Id, cancellationTokenSource.Token).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.LiveTvStreamId = streamInfo.Id; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.MediaPath = streamInfo.Path; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.InputProtocol = streamInfo.Protocol; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    await Task.Delay(1500, cancellationTokenSource.Token).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    AttachMediaStreamInfo(state, streamInfo, state.VideoRequest, state.RequestedUrl); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    checkCodecs = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    TryStreamCopy(state, state.VideoRequest); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                var videoRequest = state.VideoRequest; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (videoRequest != null && checkCodecs) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if (state.VideoStream != null && CanStreamCopyVideo(videoRequest, state.VideoStream)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        state.OutputVideoCodec = "copy"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if (state.AudioStream != null && CanStreamCopyAudio(videoRequest, state.AudioStream, state.SupportedAudioCodecs)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        state.OutputAudioCodec = "copy"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (state.MediaSource.BufferMs.HasValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                await Task.Delay(state.MediaSource.BufferMs.Value, cancellationTokenSource.Token).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1017,7 +974,7 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var transcodingId = Guid.NewGuid().ToString("N"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            var commandLineArgs = GetCommandLineArguments(outputPath, transcodingId, state, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var commandLineArgs = GetCommandLineArguments(outputPath, state, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (ApiEntryPoint.Instance.GetEncodingOptions().EnableDebugLogging) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1052,7 +1009,7 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var transcodingJob = ApiEntryPoint.Instance.OnTranscodeBeginning(outputPath, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.Request.StreamId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                state.Request.PlaySessionId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 transcodingId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 TranscodingJobType, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 process, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1123,7 +1080,7 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (state.RunTimeTicks.Value >= TimeSpan.FromMinutes(5).Ticks && state.IsInputVideo) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    transcodingJob.TranscodingThrottler = state.TranscodingThrottler = new TranscodingThrottler(transcodingJob, Logger); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    transcodingJob.TranscodingThrottler = state.TranscodingThrottler = new TranscodingThrottler(transcodingJob, Logger, ServerConfigurationManager); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     state.TranscodingThrottler.Start(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1554,7 +1511,11 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 else if (i == 21) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    request.StreamId = val; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    request.PlaySessionId = val; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                else if (i == 22) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    request.LiveStreamId = val; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1644,7 +1605,7 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 request.AudioCodec = InferAudioCodec(url); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            var state = new StreamState(LiveTvManager, Logger) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var state = new StreamState(MediaSourceManager, Logger) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 Request = request, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 RequestedUrl = url 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1658,109 +1619,28 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var item = LibraryManager.GetItemById(request.Id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            List<MediaStream> mediaStreams = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            state.ItemType = item.GetType().Name; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            state.ItemId = item.Id.ToString("N"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var archivable = item as IArchivable; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             state.IsInputArchive = archivable != null && archivable.IsArchive; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (item is ILiveTvRecording) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                var recording = await LiveTvManager.GetInternalRecording(request.Id, cancellationToken).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.VideoType = VideoType.VideoFile; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.IsInputVideo = string.Equals(recording.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                var path = recording.RecordingInfo.Path; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                var mediaUrl = recording.RecordingInfo.Url; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                var source = string.IsNullOrEmpty(request.MediaSourceId) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    ? recording.GetMediaSources(false).First() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    : MediaSourceManager.GetStaticMediaSource(recording, request.MediaSourceId, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                mediaStreams = source.MediaStreams; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                // Just to prevent this from being null and causing other methods to fail 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.MediaPath = string.Empty; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (!string.IsNullOrEmpty(path)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.MediaPath = path; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.InputProtocol = MediaProtocol.File; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                else if (!string.IsNullOrEmpty(mediaUrl)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.MediaPath = mediaUrl; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.InputProtocol = MediaProtocol.Http; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.RunTimeTicks = recording.RunTimeTicks; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.DeInterlace = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.OutputAudioSync = "1000"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.InputVideoSync = "-1"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.InputAudioSync = "1"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.InputContainer = recording.Container; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.ReadInputAtNativeFramerate = source.ReadAtNativeFramerate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            else if (item is LiveTvChannel) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            MediaSourceInfo mediaSource = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (string.IsNullOrWhiteSpace(request.LiveStreamId)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                var channel = LiveTvManager.GetInternalChannel(request.Id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.VideoType = VideoType.VideoFile; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.IsInputVideo = string.Equals(channel.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                mediaStreams = new List<MediaStream>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.DeInterlace = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var mediaSources = await MediaSourceManager.GetPlayackMediaSources(request.Id, false, cancellationToken).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                // Just to prevent this from being null and causing other methods to fail 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.MediaPath = string.Empty; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                mediaSource = string.IsNullOrEmpty(request.MediaSourceId) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                   ? mediaSources.First() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                   : mediaSources.First(i => string.Equals(i.Id, request.MediaSourceId)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                var mediaSources = await MediaSourceManager.GetPlayackMediaSources(request.Id, false, cancellationToken).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                var mediaSource = string.IsNullOrEmpty(request.MediaSourceId) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    ? mediaSources.First() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    : mediaSources.First(i => string.Equals(i.Id, request.MediaSourceId)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                mediaStreams = mediaSource.MediaStreams; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.MediaPath = mediaSource.Path; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.InputProtocol = mediaSource.Protocol; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.InputContainer = mediaSource.Container; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.InputFileSize = mediaSource.Size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.InputBitrate = mediaSource.Bitrate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.ReadInputAtNativeFramerate = mediaSource.ReadAtNativeFramerate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.RunTimeTicks = mediaSource.RunTimeTicks; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                var video = item as Video; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (video != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.IsInputVideo = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if (mediaSource.VideoType.HasValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        state.VideoType = mediaSource.VideoType.Value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.IsoType = mediaSource.IsoType; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.PlayableStreamFileNames = mediaSource.PlayableStreamFileNames.ToList(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if (mediaSource.Timestamp.HasValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        state.InputTimestamp = mediaSource.Timestamp.Value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                mediaSource = await MediaSourceManager.GetLiveStream(request.LiveStreamId, cancellationToken).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var videoRequest = request as VideoStreamRequest; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            AttachMediaStreamInfo(state, mediaStreams, videoRequest, url); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            AttachMediaSourceInfo(state, mediaSource, videoRequest, url); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var container = Path.GetExtension(state.RequestedUrl); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1801,15 +1681,7 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (videoRequest != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (state.VideoStream != null && CanStreamCopyVideo(videoRequest, state.VideoStream)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.OutputVideoCodec = "copy"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (state.AudioStream != null && CanStreamCopyAudio(videoRequest, state.AudioStream, state.SupportedAudioCodecs)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.OutputAudioCodec = "copy"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                TryStreamCopy(state, videoRequest); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             state.OutputFilePath = GetOutputFilePath(state); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1817,11 +1689,47 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return state; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        private void AttachMediaStreamInfo(StreamState state, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        private void TryStreamCopy(StreamState state, VideoStreamRequest videoRequest) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (state.VideoStream != null && CanStreamCopyVideo(videoRequest, state.VideoStream)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                state.OutputVideoCodec = "copy"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (state.AudioStream != null && CanStreamCopyAudio(videoRequest, state.AudioStream, state.SupportedAudioCodecs)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                state.OutputAudioCodec = "copy"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        private void AttachMediaSourceInfo(StreamState state, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           MediaSourceInfo mediaSource, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           VideoStreamRequest videoRequest, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           string requestedUrl) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            state.MediaPath = mediaSource.Path; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            state.InputProtocol = mediaSource.Protocol; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            state.InputContainer = mediaSource.Container; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            state.InputFileSize = mediaSource.Size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            state.InputBitrate = mediaSource.Bitrate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            state.ReadInputAtNativeFramerate = mediaSource.ReadAtNativeFramerate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            state.RunTimeTicks = mediaSource.RunTimeTicks; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (mediaSource.VideoType.HasValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                state.VideoType = mediaSource.VideoType.Value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            state.IsoType = mediaSource.IsoType; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            state.PlayableStreamFileNames = mediaSource.PlayableStreamFileNames.ToList(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (mediaSource.Timestamp.HasValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                state.InputTimestamp = mediaSource.Timestamp.Value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             state.InputProtocol = mediaSource.Protocol; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             state.MediaPath = mediaSource.Path; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             state.RunTimeTicks = mediaSource.RunTimeTicks; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1830,21 +1738,16 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             state.InputFileSize = mediaSource.Size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             state.ReadInputAtNativeFramerate = mediaSource.ReadAtNativeFramerate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (state.ReadInputAtNativeFramerate) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (state.ReadInputAtNativeFramerate || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                mediaSource.Protocol == MediaProtocol.File && string.Equals(mediaSource.Container, "wtv", StringComparison.OrdinalIgnoreCase)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 state.OutputAudioSync = "1000"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 state.InputVideoSync = "-1"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 state.InputAudioSync = "1"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            AttachMediaStreamInfo(state, mediaSource.MediaStreams, videoRequest, requestedUrl); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var mediaStreams = mediaSource.MediaStreams; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        private void AttachMediaStreamInfo(StreamState state, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            List<MediaStream> mediaStreams, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            VideoStreamRequest videoRequest, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            string requestedUrl) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (videoRequest != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (string.IsNullOrEmpty(videoRequest.VideoCodec)) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1873,7 +1776,7 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 state.AudioStream = GetMediaStream(mediaStreams, null, MediaStreamType.Audio, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            state.AllMediaStreams = mediaStreams; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            state.MediaSource = mediaSource; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         private bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2109,7 +2012,6 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var audioCodec = state.ActualOutputAudioCodec; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var videoCodec = state.ActualOutputVideoCodec; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var mediaProfile = state.VideoRequest == null ? 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2130,7 +2032,9 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 state.TargetTimestamp, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 state.IsTargetAnamorphic, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 state.IsTargetCabac, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.TargetRefFrames); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                state.TargetRefFrames, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                state.TargetVideoStreamCount, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                state.TargetAudioStreamCount); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (mediaProfile != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2215,7 +2119,9 @@ namespace MediaBrowser.Api.Playback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     state.TranscodeSeekInfo, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     state.IsTargetAnamorphic, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     state.IsTargetCabac, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.TargetRefFrames 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    state.TargetRefFrames, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    state.TargetVideoStreamCount, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    state.TargetAudioStreamCount 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     ).FirstOrDefault() ?? string.Empty; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 |