using MediaBrowser.Common.IO; using MediaBrowser.Model.Logging; using ServiceStack.Service; using ServiceStack.ServiceHost; using System; 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; } /// /// 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. public ProgressiveStreamWriter(string path, ILogger logger) { Path = path; Logger = logger; } /// /// 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 StreamFile(Path, responseStream).ConfigureAwait(false); } catch (Exception ex) { Logger.ErrorException("Error streaming media", ex); throw; } finally { ApiEntryPoint.Instance.OnTranscodeEndRequest(Path, TranscodingJobType.Progressive); } } /// /// Streams the file. /// /// The path. /// The output stream. /// Task{System.Boolean}. private async Task StreamFile(string path, Stream outputStream) { var eofCount = 0; long position = 0; using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous)) { 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; } } } } }