using MediaBrowser.Common.IO; using MediaBrowser.Model.Logging; using ServiceStack.Web; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; namespace MediaBrowser.Api.Playback.Progressive { public class ProgressiveStreamWriter : IStreamWriter, IHasOptions { private string Path { get; set; } private ILogger Logger { get; set; } private readonly IFileSystem _fileSystem; /// /// The _options /// private readonly IDictionary _options = new Dictionary(); /// /// Gets the options. /// /// The options. public IDictionary Options { get { return _options; } } /// /// Initializes a new instance of the class. /// /// The path. /// The logger. /// The file system. public ProgressiveStreamWriter(string path, ILogger logger, IFileSystem fileSystem) { Path = path; Logger = logger; _fileSystem = fileSystem; } /// /// Writes to. /// /// The response stream. public void WriteTo(Stream responseStream) { var task = WriteToAsync(responseStream); Task.WaitAll(task); } /// /// Writes to async. /// /// The response stream. /// Task. public async Task WriteToAsync(Stream responseStream) { try { await new ProgressiveFileCopier(_fileSystem).StreamFile(Path, responseStream).ConfigureAwait(false); } catch { Logger.Error("Error streaming media. The client has most likely disconnected or transcoding has failed."); throw; } finally { ApiEntryPoint.Instance.OnTranscodeEndRequest(Path, TranscodingJobType.Progressive); } } } public class ProgressiveFileCopier { private readonly IFileSystem _fileSystem; public ProgressiveFileCopier(IFileSystem fileSystem) { _fileSystem = fileSystem; } public async Task StreamFile(string path, Stream outputStream) { var eofCount = 0; long position = 0; using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) { while (eofCount < 15) { await fs.CopyToAsync(outputStream).ConfigureAwait(false); var fsPosition = fs.Position; var bytesRead = fsPosition - position; //Logger.Debug("Streamed {0} bytes from file {1}", bytesRead, path); if (bytesRead == 0) { eofCount++; await Task.Delay(100).ConfigureAwait(false); } else { eofCount = 0; } position = fsPosition; } } } } }