 .../Code/ImageMediaSource.cs                       |  15 ++-
 .../Transcoders/Direct.cs                          | 113 ++++++++++++++++++++-
 .../Units/InputUnit.cs                             |  82 ++++++++++++++-
 3 files changed, 200 insertions(+), 10 deletions(-)

diff --git a/Services/MPExtended.Services.StreamingService/Code/ImageMediaSource.cs b/Services/MPExtended.Services.StreamingService/Code/ImageMediaSource.cs
index c8c28288..becc7227 100644
--- a/Services/MPExtended.Services.StreamingService/Code/ImageMediaSource.cs
+++ b/Services/MPExtended.Services.StreamingService/Code/ImageMediaSource.cs
@@ -65,7 +65,7 @@ public ImageMediaSource(string path)
         }
 
         public ImageMediaSource(WebMediaType type, int? provider, string id, WebFileType filetype, int offset)
-            : base (type, provider, id, filetype, offset)
+            : base(type, provider, id, filetype, offset)
         {
         }
 
@@ -108,9 +108,18 @@ public override WebFileInfo GetFileInfo()
                 int idChannel = MediaType == WebMediaType.TV || MediaType == WebMediaType.Radio ?
                     Int32.Parse(Id) :
                     Connections.TAS.GetRecordingById(Int32.Parse(Id)).ChannelId;
+
+                // get the channel, the channel may no longer exist for recording.  
                 var channel = Connections.TAS.GetChannelBasicById(idChannel);
+                if (channel == null)
+                {
+                    Log.Debug("Did not find the tv channel with id {0}", idChannel);
+                    fileInfoCache = new WebFileInfo() { Exists = false };
+                    return fileInfoCache;
+                }
+
                 string location = _logos.FindLocation(channel.Title);
-                if(location == null)
+                if (location == null)
                 {
                     Log.Debug("Did not find tv logo for channel {0} with id {1}", channel.Title, idChannel);
                     fileInfoCache = new WebFileInfo() { Exists = false };
@@ -131,7 +140,7 @@ public override WebFileInfo GetFileInfo()
                                           .FirstOrDefault();
                 if (preferedItem == null)
                 {
-                    Log.Debug("Requested prefered artwork item for provider={0} mediatype={1} filetype={2} id={3}, but no artwork found", 
+                    Log.Debug("Requested prefered artwork item for provider={0} mediatype={1} filetype={2} id={3}, but no artwork found",
                         Provider, MediaType, FileType, Id);
                     fileInfoCache = new WebFileInfo()
                     {
diff --git a/Services/MPExtended.Services.StreamingService/Transcoders/Direct.cs b/Services/MPExtended.Services.StreamingService/Transcoders/Direct.cs
index 9ab25f04..9c7ae938 100644
--- a/Services/MPExtended.Services.StreamingService/Transcoders/Direct.cs
+++ b/Services/MPExtended.Services.StreamingService/Transcoders/Direct.cs
@@ -19,7 +19,11 @@
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using System.Net;
+using System.ServiceModel.Web;
 using System.Text;
+using System.Text.RegularExpressions;
+using Microsoft.Win32;
 using MPExtended.Libraries.Service;
 using MPExtended.Libraries.Service.Util;
 using MPExtended.Services.Common.Interfaces;
@@ -33,6 +37,20 @@ internal class Direct : ITranscoder, IRetrieveHookTranscoder
         public string Identifier { get; set; }
         public StreamContext Context { get; set; }
 
+        private static Lazy<Dictionary<string, string>> mimeDatabase = new Lazy<Dictionary<string, string>>(CreateMimeDatabase, true);
+        private static readonly string[] usedTypes = new[] { "video", "audio", "image" };
+        private static readonly Regex bytes = new Regex(@"^bytes=(\d+)(?:-(\d+)?)?$", RegexOptions.Compiled);
+
+        /// <summary>
+        /// Get from MIME-Database in Registry
+        /// </summary>
+        /// <param name="extention"></param>
+        /// <returns></returns>
+        public static bool TryGetMime(string extention, out string mime)
+        {
+            return mimeDatabase.Value.TryGetValue(extention, out mime);
+        }
+
         public string GetStreamURL()
         {
             return WCFUtil.GetCurrentRoot() + "StreamingService/stream/RetrieveStream?identifier=" + Identifier;
@@ -48,17 +66,102 @@ public void BuildPipeline()
 
         public void RetrieveStreamCalled()
         {
+            string mime;
+            if (!TryGetMime(Path.GetExtension(Context.Source.GetFileInfo().Name), out mime))
+                mime = "application/octet-stream";
+
+            WCFUtil.SetContentType(mime);
+            WCFUtil.AddHeader("Last-Modified", Context.Source.GetFileInfo().LastModifiedTime.ToString("r", System.Globalization.CultureInfo.InvariantCulture));
+            StreamLog.Info(Identifier, "*RetrieveStream Source={0}, MediaType={1}, ContenType={2}", Context.Source.GetFileInfo().Name, Context.Source.MediaType, mime);
+
+
             // Don't return a length when we're streaming TV, as we don't know the full length of the stream, since we are
             // reading from a timeshifting buffer. See dicussion in bug #394 and #319. 
             if (Context.Source.MediaType != WebMediaType.TV)
-                WCFUtil.SetContentLength(Context.Source.GetFileInfo().Size);
+            {
+                var stream = Context.Pipeline.GetFinalStream();
+                string range = WebOperationContext.Current.IncomingRequest.Headers["Range"];
+                if (range != null)
+                {
+                    //Test the Stream is Closed, Closed Why? WCF Close the Stream on EOF see DirectStream.cs
+                    StreamLog.Info(Identifier, "Range requested: '{0}' - can {1}Seek", range, !stream.CanSeek ? "not " : string.Empty);
+                    if (!stream.CanSeek)
+                    {
+                        WCFUtil.AddHeader("Accept-Ranges", "none");
+                        WCFUtil.SetContentLength(Context.Source.GetFileInfo().Size);
+                        return;
+                    }
+
+                    long totalLength = Context.Source.GetFileInfo().Size;
+                    long sendCount = totalLength;
+                    long start = 0L;
+                    long end = totalLength - 1;
+
+                    if (!TryGetRange(range, totalLength, ref start, ref end))
+                    {
+                        WCFUtil.SetResponseCode(HttpStatusCode.RequestedRangeNotSatisfiable);
+                        WCFUtil.AddHeader("Connection", "close");
+                        StreamLog.Debug(Identifier, "RangeNotSatisfiable: '{0}'", range);
+                        return;
+                    }
+
+                    var contentrange = string.Format("bytes {0}-{1}/{2}", start, end, totalLength);
+                    sendCount = end - start + 1;
+
+                    StreamLog.Debug(Identifier, "Range set: {0}", contentrange);
+                    StreamLog.Info(Identifier, "SeekTo: {0}", start);
+                    stream.Position = start;
 
-            // there has to be a better way to do this
-            object mime = RegistryReader.ReadKey(Microsoft.Win32.RegistryHive.ClassesRoot, Path.GetExtension(Context.Source.GetFileInfo().Name), "Content Type");
-            if (mime != null)
+                    WCFUtil.AddHeader("Accept-Ranges", "bytes");
+                    WCFUtil.AddHeader("Content-Range", contentrange);
+                    WCFUtil.SetContentLength(sendCount);
+                    WCFUtil.SetResponseCode(HttpStatusCode.PartialContent);
+                }
+            }
+        }
+
+        private bool TryGetRange(string range, long totalLength, ref long start, ref long end)
+        {
+            var m = bytes.Match(range);
+            if (m.Success)
+            {
+                if (long.TryParse(m.Groups[1].Value, out start) && start >= 0)
+                {
+                    if (m.Groups.Count != 3 || !long.TryParse(m.Groups[2].Value, out end) || end <= start || end >= totalLength)
+                    {
+                        end = totalLength - 1;
+                    }
+                    return !(start >= totalLength);
+                }
+            }
+            return false;
+        }
+
+        private static Dictionary<string, string> CreateMimeDatabase()
+        {
+            var mimeDatabase = new Dictionary<string, string>();
+
+            using (RegistryKey database = Registry.ClassesRoot.OpenSubKey("MIME\\Database\\Content Type"))
             {
-                WCFUtil.SetContentType(mime.ToString());
+                if (database != null)
+                {
+                    foreach (string mimeType in database.GetSubKeyNames().Where(mt => usedTypes.Count(ut => mt.StartsWith(ut)) > 0))
+                    {
+                        using (RegistryKey mimeKey = database.OpenSubKey(mimeType))
+                        {
+                            var extension = mimeKey.GetValue("Extension") as string;
+                            if (!string.IsNullOrWhiteSpace(extension))
+                                mimeDatabase[extension] = mimeType;
+                        }
+                    }
+                }
             }
+
+            mimeDatabase.Add(".tsbuffer", "video/mp2ts");
+            if (!mimeDatabase.ContainsKey(".ts"))
+                mimeDatabase.Add(".ts", "video/mp2ts");
+
+            return mimeDatabase;
         }
     }
 }
diff --git a/Services/MPExtended.Services.StreamingService/Units/InputUnit.cs b/Services/MPExtended.Services.StreamingService/Units/InputUnit.cs
index e9bbda79..b132696d 100644
--- a/Services/MPExtended.Services.StreamingService/Units/InputUnit.cs
+++ b/Services/MPExtended.Services.StreamingService/Units/InputUnit.cs
@@ -55,7 +55,9 @@ public bool Setup()
                 else
                 {
                     StreamLog.Info(identifier, "Using FileStream to read input");
-                    DataOutputStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
+                    //                    DataOutputStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
+                    var baseStram = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, short.MaxValue, FileOptions.RandomAccess);
+                    DataOutputStream = new DirectStream(baseStram, identifier);
                 }
             }
             catch (Exception e)
@@ -73,8 +75,84 @@ public bool Start()
 
         public bool Stop()
         {
-            DataOutputStream.Close();
+            var directStream = DataOutputStream as DirectStream;
+            if (directStream != null)
+                directStream.Stop();
+            else DataOutputStream.Close();
             return true;
         }
+
+        #region Helper class DirectStream
+
+        /// <summary>
+        /// A Wraper for Ignore Close from WCF while Seeking
+        /// </summary>
+        public class DirectStream : Stream
+        {
+            Stream baseStream;
+            string identifier;
+
+            public DirectStream(Stream baseStream, string identifier)
+            {
+                this.baseStream = baseStream;
+                this.identifier = identifier;
+            }
+
+            public override bool CanRead { get {return baseStream.CanRead; } }
+
+            public override bool CanSeek { get {return baseStream.CanSeek;} }
+
+            public override bool CanWrite { get { return false; } }
+
+            public override long Length { get { return baseStream.Length; } }
+
+            public override long Position
+            {
+                get { return baseStream.Position; }
+                set { baseStream.Position = value; }
+            }
+
+            public override void Flush()
+            {
+                throw new NotImplementedException();
+            }
+
+            public override int Read(byte[] buffer, int offset, int count)
+            {
+                return baseStream.Read(buffer, offset, count);
+            }
+
+            public override long Seek(long offset, SeekOrigin origin)
+            {
+                return baseStream.Seek(offset, origin);
+            }
+
+            public override void SetLength(long value)
+            {
+                baseStream.SetLength(value);
+            }
+
+            public override void Write(byte[] buffer, int offset, int count)
+            {
+                throw new NotImplementedException();
+            }
+
+            /// <summary>
+            /// Close is ignored! Use <see cref="Stop"/> to Close the stream
+            /// </summary>
+            public override void Close()
+            {
+                if (CanSeek)
+                    StreamLog.Debug(identifier, "DirectStream Close ignored");
+            }
+
+            public void Stop()
+            {
+                base.Close();
+                StreamLog.Debug(identifier, "DirectStream Close");
+            }
+        }
+
+        #endregion
     }
 }
