public static Stream ExtractImage(MediaSource source, int startPosition, int? maxWidth, int? maxHeight) { if (!source.IsLocalFile) { Log.Warn("ExtractImage: Source type={0} id={1} is not supported yet", source.MediaType, source.Id); WCFUtil.SetResponseCode(System.Net.HttpStatusCode.NotImplemented); return null; } // calculate size string ffmpegResize = ""; if (maxWidth != null && maxHeight != null) { try { decimal resolution = MediaInfoWrapper.GetMediaInfo(source).VideoStreams.First().DisplayAspectRatio; ffmpegResize = "-s " + Resolution.Calculate(resolution, new Resolution(maxWidth.Value, maxHeight.Value)).ToString(); } catch (Exception ex) { Log.Error("Error while getting resolution of video stream", ex); } } // get temporary filename string tempDir = Path.Combine(Path.GetTempPath(), "MPExtended", "imagecache"); if (!Directory.Exists(tempDir)) { Directory.CreateDirectory(tempDir); } string filename = String.Format("ex_{0}_{1}_{2}_{3}.jpg", source.GetUniqueIdentifier(), startPosition, maxWidth == null ? "null" : maxWidth.ToString(), maxHeight == null ? "null" : maxHeight.ToString()); string tempFile = Path.Combine(tempDir, filename); // maybe it exists if (File.Exists(tempFile)) { return StreamImage(new ImageSource(tempFile)); } // execute it ProcessStartInfo info = new ProcessStartInfo(); info.Arguments = String.Format("-ss {0} -vframes 1 -i \"{1}\" {2} -f image2 {3}", startPosition, source.GetPath(), ffmpegResize, tempFile); info.FileName = Configuration.Streaming.FFMpegPath; info.CreateNoWindow = true; info.UseShellExecute = false; Process proc = new Process(); proc.StartInfo = info; proc.Start(); proc.WaitForExit(); // log when failed if (!File.Exists(tempFile)) { Log.Warn("Failed to extract image to temporary file {0}", tempFile); WCFUtil.SetResponseCode(System.Net.HttpStatusCode.InternalServerError); return null; } return StreamImage(new ImageSource(tempFile)); }
public static Stream ExtractImage(MediaSource source, long position, int? maxWidth, int? maxHeight, string borders, string format) { if (!source.Exists) { Log.Warn("ExtractImage: Source {0} (resolved to path {1}) doesn't exists", source.GetDebugName(), source.GetPath()); WCFUtil.SetResponseCode(System.Net.HttpStatusCode.NotFound); return Stream.Null; } if (!source.SupportsDirectAccess) { Log.Warn("ExtractImage: Extracting images from remote sources isn't supported yet", source.MediaType, source.Id); WCFUtil.SetResponseCode(System.Net.HttpStatusCode.NotImplemented); return Stream.Null; } // get temporary filename string filename = String.Format("extract_{0}_{1}.jpg", source.GetUniqueIdentifier(), position); string tempFile = cache.GetPath(filename); // maybe it exists in cache, return that then if (cache.Contains(filename)) { return StreamPostprocessedImage(new ImageMediaSource(tempFile), maxWidth, maxHeight, borders, format); } // execute it ProcessStartInfo info = new ProcessStartInfo(); using (var impersonator = source.GetImpersonator()) { info.Arguments = String.Format("-ss {0} -i \"{1}\" -vframes 1 -f image2 {2}", position, source.GetPath(), tempFile); info.FileName = Configuration.StreamingProfiles.FFMpegPath; info.CreateNoWindow = true; info.UseShellExecute = false; Process proc = new Process(); proc.StartInfo = info; proc.Start(); proc.WaitForExit(); } // log when failed if (!File.Exists(tempFile)) { Log.Warn("Failed to extract image to temporary file {0} with command {1}", tempFile, info.Arguments); WCFUtil.SetResponseCode(System.Net.HttpStatusCode.InternalServerError); return Stream.Null; } return StreamPostprocessedImage(new ImageMediaSource(tempFile), maxWidth, maxHeight, borders, format); }
public static Stream ExtractImage(MediaSource source, long position, int?maxWidth, int?maxHeight, string borders, string format) { if (!source.Exists) { Log.Warn("ExtractImage: Source {0} (resolved to path {1}) doesn't exists", source.GetDebugName(), source.GetPath()); WCFUtil.SetResponseCode(System.Net.HttpStatusCode.NotFound); return(Stream.Null); } if (!source.SupportsDirectAccess) { Log.Warn("ExtractImage: Extracting images from remote sources isn't supported yet", source.MediaType, source.Id); WCFUtil.SetResponseCode(System.Net.HttpStatusCode.NotImplemented); return(Stream.Null); } // get temporary filename string filename = String.Format("extract_{0}_{1}.jpg", source.GetUniqueIdentifier(), position); string tempFile = cache.GetPath(filename); // maybe it exists in cache, return that then if (cache.Contains(filename)) { // if source is newer, cached image needs to be recreated if (source.GetFileInfo().LastModifiedTime > cache.GetLastModifiedTime(tempFile)) { cache.Invalidate(filename); } else { return(StreamPostprocessedImage(new ImageMediaSource(tempFile), maxWidth, maxHeight, borders, format)); } } // We need to impersonate to access the network drive and check if the thumbnail already exists. However, because // impersonation is lost when starting a process, we can't start ffmpeg from in here. We need to check whether the // file is accessible from outside the impersonation context again, and start the ffmpeg process as a different user // if that is the case. string fullPath; using (var context = source.CreateNetworkContext()) { fullPath = context.RewritePath(source.GetPath()); // stream a pre-existing thumbnail, if possible if (source.MediaType == WebMediaType.Recording && Path.GetExtension(fullPath).ToLower() == ".ts") { var thumbnailFileInfo = new FileInfo(Path.ChangeExtension(fullPath, ".jpg")); if (thumbnailFileInfo.Exists && thumbnailFileInfo.Length > 0) { return(StreamPostprocessedImage(new ImageMediaSource(thumbnailFileInfo.FullName), maxWidth, maxHeight, borders, format)); } } } // finally, extract the image with ffmpeg if everything else has failed bool extractResult = ExecuteFFMpegExtraction(source, fullPath, position, tempFile); if (!extractResult) { WCFUtil.SetResponseCode(System.Net.HttpStatusCode.InternalServerError); return(Stream.Null); } return(StreamPostprocessedImage(new ImageMediaSource(tempFile), maxWidth, maxHeight, borders, format)); }
public static Stream ExtractImage(MediaSource source, long startPosition, int?maxWidth, int?maxHeight) { if (!source.Exists) { Log.Warn("ExtractImage: Source {0} (resolved to path {1}) doesn't exists", source.GetDebugName(), source.GetPath()); WCFUtil.SetResponseCode(System.Net.HttpStatusCode.NotFound); return(Stream.Null); } if (!source.SupportsDirectAccess) { Log.Warn("ExtractImage: Extracting images from remote sources isn't supported yet", source.MediaType, source.Id); WCFUtil.SetResponseCode(System.Net.HttpStatusCode.NotImplemented); return(Stream.Null); } // calculate size string ffmpegResize = ""; if (maxWidth != null || maxHeight != null) { try { decimal resolution = MediaInfoWrapper.GetMediaInfo(source).VideoStreams.First().DisplayAspectRatio; ffmpegResize = "-s " + Resolution.Calculate(resolution, maxWidth, maxHeight).ToString(); } catch (Exception ex) { Log.Error("Error while getting resolution of video stream, not resizing", ex); } } // get temporary filename string filename = String.Format("extract_{0}_{1}_{2}_{3}.jpg", source.GetUniqueIdentifier(), startPosition, maxWidth == null ? "null" : maxWidth.ToString(), maxHeight == null ? "null" : maxHeight.ToString()); string tempFile = cache.GetPath(filename); // maybe it exists in cache, return that then if (cache.Contains(filename)) { return(StreamImage(new ImageMediaSource(tempFile))); } // execute it ProcessStartInfo info = new ProcessStartInfo(); using (var impersonator = source.GetImpersonator()) { info.Arguments = String.Format("-ss {0} -i \"{1}\" {2} -vframes 1 -f image2 {3}", startPosition, source.GetPath(), ffmpegResize, tempFile); info.FileName = Configuration.Streaming.FFMpegPath; info.CreateNoWindow = true; info.UseShellExecute = false; Process proc = new Process(); proc.StartInfo = info; proc.Start(); proc.WaitForExit(); } // log when failed if (!File.Exists(tempFile)) { Log.Warn("Failed to extract image to temporary file {0} with command {1}", tempFile, info.Arguments); WCFUtil.SetResponseCode(System.Net.HttpStatusCode.InternalServerError); return(Stream.Null); } return(StreamImage(new ImageMediaSource(tempFile))); }
public static Stream ExtractImage(MediaSource source, int startPosition, int? maxWidth, int? maxHeight) { if (!source.Exists) { Log.Warn("ExtractImage: Source {0} (resolved to path {1}) doesn't exists", source.GetDebugName(), source.GetPath()); WCFUtil.SetResponseCode(System.Net.HttpStatusCode.NotFound); return Stream.Null; } if (!source.SupportsDirectAccess) { Log.Warn("ExtractImage: Extracting images from remote sources isn't supported yet", source.MediaType, source.Id); WCFUtil.SetResponseCode(System.Net.HttpStatusCode.NotImplemented); return Stream.Null; } // calculate size string ffmpegResize = ""; if (maxWidth != null || maxHeight != null) { try { decimal resolution = MediaInfoWrapper.GetMediaInfo(source).VideoStreams.First().DisplayAspectRatio; ffmpegResize = "-s " + Resolution.Calculate(resolution, maxWidth, maxHeight).ToString(); } catch (Exception ex) { Log.Error("Error while getting resolution of video stream, not resizing", ex); } } // get temporary filename string tempDir = Path.Combine(Installation.GetCacheDirectory(), "imagecache"); if (!Directory.Exists(tempDir)) { Directory.CreateDirectory(tempDir); } string filename = String.Format("extract_{0}_{1}_{2}_{3}.jpg", source.GetUniqueIdentifier(), startPosition, maxWidth == null ? "null" : maxWidth.ToString(), maxHeight == null ? "null" : maxHeight.ToString()); string tempFile = Path.Combine(tempDir, filename); // maybe it exists in cache, return that then if (File.Exists(tempFile)) { return StreamImage(new ImageMediaSource(tempFile)); } // execute it ProcessStartInfo info = new ProcessStartInfo(); using (var impersonator = source.GetImpersonator()) { info.Arguments = String.Format("-ss {0} -i \"{1}\" {2} -vframes 1 -f image2 {3}", startPosition, source.GetPath(), ffmpegResize, tempFile); info.FileName = Configuration.Streaming.FFMpegPath; info.CreateNoWindow = true; info.UseShellExecute = false; Process proc = new Process(); proc.StartInfo = info; proc.Start(); proc.WaitForExit(); } // log when failed if (!File.Exists(tempFile)) { Log.Warn("Failed to extract image to temporary file {0} with command {1}", tempFile, info.Arguments); WCFUtil.SetResponseCode(System.Net.HttpStatusCode.InternalServerError); return Stream.Null; } return StreamImage(new ImageMediaSource(tempFile)); }
public static Stream ExtractImage(MediaSource source, long position, int? maxWidth, int? maxHeight, string borders, string format) { if (!source.Exists) { Log.Warn("ExtractImage: Source {0} (resolved to path {1}) doesn't exists", source.GetDebugName(), source.GetPath()); WCFUtil.SetResponseCode(System.Net.HttpStatusCode.NotFound); return Stream.Null; } if (!source.SupportsDirectAccess) { Log.Warn("ExtractImage: Extracting images from remote sources isn't supported yet", source.MediaType, source.Id); WCFUtil.SetResponseCode(System.Net.HttpStatusCode.NotImplemented); return Stream.Null; } // get temporary filename string filename = String.Format("extract_{0}_{1}.jpg", source.GetUniqueIdentifier(), position); string tempFile = cache.GetPath(filename); // maybe it exists in cache, return that then if (cache.Contains(filename)) { // if source is newer, cached image needs to be recreated if (source.GetFileInfo().LastModifiedTime > cache.GetLastModifiedTime(tempFile)) { cache.Invalidate(filename); } else { return StreamPostprocessedImage(new ImageMediaSource(tempFile), maxWidth, maxHeight, borders, format); } } // We need to impersonate to access the network drive and check if the thumbnail already exists. However, because // impersonation is lost when starting a process, we can't start ffmpeg from in here. We need to check whether the // file is accessible from outside the impersonation context again, and start the ffmpeg process as a different user // if that is the case. string fullPath; using (var context = source.CreateNetworkContext()) { fullPath = context.RewritePath(source.GetPath()); // stream a pre-existing thumbnail, if possible if (source.MediaType == WebMediaType.Recording && Path.GetExtension(fullPath).ToLower() == ".ts") { var thumbnailFileInfo = new FileInfo(Path.ChangeExtension(fullPath, ".jpg")); if (thumbnailFileInfo.Exists && thumbnailFileInfo.Length > 0) return StreamPostprocessedImage(new ImageMediaSource(thumbnailFileInfo.FullName), maxWidth, maxHeight, borders, format); } } // finally, extract the image with ffmpeg if everything else has failed bool extractResult = ExecuteFFMpegExtraction(source, fullPath, position, tempFile); if (!extractResult) { WCFUtil.SetResponseCode(System.Net.HttpStatusCode.InternalServerError); return Stream.Null; } return StreamPostprocessedImage(new ImageMediaSource(tempFile), maxWidth, maxHeight, borders, format); }
public WebMediaInfo GetForSource(MediaSource src) { return cache[src.GetUniqueIdentifier()]; }
public void Save(MediaSource src, WebMediaInfo info) { lock (cache) { cache[src.GetUniqueIdentifier()] = info; } isDirty = true; }
public bool HasForSource(MediaSource src) { return cache.ContainsKey(src.GetUniqueIdentifier()); }
public void Save(MediaSource src, CachedInfoWrapper info) { lock (cache) cache[src.GetUniqueIdentifier()] = info; isDirty = true; }
public CachedInfoWrapper GetForSource(MediaSource src) { return cache[src.GetUniqueIdentifier()]; }
public static Stream GetResizedImage(MediaSource source, WebArtworkType artworktype, int maxWidth, int maxHeight) { // load file ImageSource src = ConvertToImageSource(source, artworktype); if (src == null) { WCFUtil.SetResponseCode(System.Net.HttpStatusCode.NotFound); return null; } // create cache path string tmpDir = Path.Combine(Path.GetTempPath(), "MPExtended", "imagecache"); if (!Directory.Exists(tmpDir)) Directory.CreateDirectory(tmpDir); string cachedPath = Path.Combine(tmpDir, String.Format("rs_{0}_{1}_{2}_{3}.jpg", source.GetUniqueIdentifier(), artworktype, maxWidth, maxHeight)); // check for existence on disk if (!File.Exists(cachedPath)) { Image orig = Image.FromStream(src.GetDataStream()); if (!ResizeImage(orig, cachedPath, maxWidth, maxHeight)) { return null; } } return StreamImage(new ImageSource(cachedPath)); }