private async void CalculateAudioGain_Click(object sender, RoutedEventArgs e) { CalculateAudioGain.IsEnabled = false; CalculateAudioGain.Content = "Wait"; float?Gain = await Task.Run(() => AvisynthTools.GetAudioGain(encodeSettings.FilePath, null)); if (Gain.HasValue) { encodeSettings.AudioGain = Gain; } CalculateAudioGain.IsEnabled = true; CalculateAudioGain.Content = "Auto"; }
public CompletionStatus GenerateDeshakerLog(MediaEncoderSettings settings, string inputFile) { // Prepare Deshaker settings. settings.DeshakerSettings.Pass = 1; settings.DeshakerSettings.LogFile = settings.DeshakerTempLog; settings.DeshakerSettings.SourcePixelAspectRatio = settings.SourceAspectRatio.Value; // settings.DeshakerSettings.AppendToFile = true; File.Delete(settings.DeshakerLog); // Start UI. CompletionStatus Result = CompletionStatus.Success; object JobId = "Deshaker"; FFmpegConfig.UserInterfaceManager.Start(JobId, "Running Deshaker Prescan"); ProcessStartOptions JobOptions = new ProcessStartOptions(JobId, "Getting Frame Count", false); // Get frame count. settings.CalculateSize(); int FrameStart = (int)((settings.DeshakerSettings.PrescanStart ?? 0) * settings.SourceFrameRate.Value); int FrameEnd = (int)((settings.DeshakerSettings.PrescanEnd ?? 0) * settings.SourceFrameRate.Value); string Script = MediaEncoderScript.GenerateDeshakerScript(settings, inputFile, 0, FrameStart, FrameEnd); File.WriteAllText(settings.DeshakerScript, Script); JobOptions.FrameCount = AvisynthTools.GetFrameCount(settings.DeshakerScript, JobOptions); // Pad file start. using (StreamWriter sw = new StreamWriter(File.Open(settings.DeshakerLog, FileMode.Create), Encoding.ASCII)) { for (int i = 0; i < FrameStart; i++) { sw.WriteLine((i + 1).ToString().PadLeft(7) + " skipped # 0.00 0.00 "); } } // Run segments. var Segments = settings.DeshakerSettings.Segments; if (JobOptions.FrameCount > 0) { for (int i = 0; i < Segments.Count; i++) { // Get start position of next segment. long NextSegmentStart = i < Segments.Count - 1 ? Segments[i + 1].FrameStart : 0; if (NextSegmentStart == 0 || NextSegmentStart > FrameStart) { // Enforce PrescanStart for preview long SegmentStart = Segments[i].FrameStart; long SegmentEnd = NextSegmentStart > 0 ? NextSegmentStart - 1 : 0; // Enforce PrescanEnd for preview if ((FrameEnd > 0 && SegmentStart > FrameEnd) || (SegmentEnd > 0 && SegmentStart > SegmentEnd)) break; if ((FrameStart > 0 && FrameStart > SegmentStart) || SegmentStart == 0) SegmentStart = FrameStart; if ((FrameEnd > 0 && FrameEnd < SegmentEnd) || SegmentEnd == 0) SegmentEnd = FrameEnd; Result = GenerateDeshakerLogSegment(settings, inputFile, i, FrameStart, SegmentStart, SegmentEnd, JobOptions); if (Result != CompletionStatus.Success) break; // Merge log segment into log file and set right frame numbers. using (StreamWriter sw = new StreamWriter(File.Open(settings.DeshakerLog, FileMode.Append), Encoding.ASCII)) { using (StreamReader sr = new StreamReader(File.OpenRead(settings.DeshakerTempLog), Encoding.ASCII)) { string LogLine, LogNum, LogNumField, LineOut; long NewLineNum = SegmentStart; LogLine = sr.ReadLine(); while (LogLine != null) { if (LogLine.Length > 7) { LogNum = LogLine.Substring(0, 7).Trim(); if (LogNum.Length > 0) { LogNumField = LogNum[LogNum.Length - 1].ToString(); if (LogNumField != "A" && LogNumField != "B") // For interlaced videos LogNumField = ""; NewLineNum++; // Log file starts at 1, not 0. LineOut = (NewLineNum.ToString() + LogNumField).PadLeft(7) + LogLine.Substring(7, LogLine.Length - 8); sw.WriteLine(LineOut); } } LogLine = sr.ReadLine(); } } } File.Delete(settings.DeshakerTempLog); } } } else Result = CompletionStatus.Error; // End UI. FFmpegConfig.UserInterfaceManager.Stop(JobId); return Result; }
/// <summary> /// Analyzes output files to determine what work is done and what needs to be done. /// </summary> /// <param name="settings">The media encoder settings of the job to scan.</param> /// <returns>Whether job needs to execute.</returns> public void Analyze(MediaEncoderSettings settings) { int Threads = settings.ParallelProcessing; if (Threads == 0) { Threads = 1; } this.settings = settings; SegDone = new List <SegmentInfo>(); SegLeft = new List <SegmentInfo>(); // Get script total frame count, and run in background until all other files are scanned. EncoderBusiness.EditStartPosition(settings.ScriptFile, 0, 0); ProcessStartOptions Options = new ProcessStartOptions(settings.JobIndex, "Analyzing Segments...", false).TrackProcess(settings); Task <long> TaskCount = Task.Run(() => AvisynthTools.GetFrameCount(settings.ScriptFile, Options)); // Get list of output files in folder. The number after "_Output_" is the frame position of that segment. string FileName = string.Format("Job{0}_Output_", settings.JobIndex); string FileNameExt = string.Format(".{0}", settings.Container); string[] SegFiles = Directory.GetFiles(PathManager.TempFilesPath, FileName + "*" + FileNameExt); // Scan each segment file and discard files smaller than 10kb or of less than 10 frames. // Create a list of tasks to run them all in parallel. List <Task <KeyValuePair <string, long> > > TaskList = new List <Task <KeyValuePair <string, long> > >(); foreach (string seg in SegFiles) { if (settings.CompletionStatus == CompletionStatus.Cancelled) { break; } // Discard empty files. if (new FileInfo(seg).Length > 0) { // string SegmentLocal = seg; TaskList.Add(Task.Run(() => { return(new KeyValuePair <string, long>(seg, MediaInfo.GetFrameCount(seg, null))); })); } else { File.Delete(seg); } } // Run all segment length queries simultaneously and analyze results to fill SegDone. Task.WaitAll(TaskList.ToArray()); string SegFile; long SegStart; bool SegAdded; int Pos; string SegText; if (settings.CompletionStatus != CompletionStatus.Cancelled) { foreach (var item in TaskList) { SegFile = item.Result.Key; SegStart = 0; SegAdded = false; if (item.Result.Value >= 1) // Segment must contain at least one valid frame. { Pos = SegFile.IndexOf(FileName); if (Pos > -1) { Pos += FileName.Length; SegText = SegFile.Substring(Pos, SegFile.Length - Pos - FileNameExt.Length); if (long.TryParse(SegText, out SegStart)) { SegDone.Add(new SegmentInfo(SegStart, SegStart + item.Result.Value)); SegAdded = true; } } } if (!SegAdded) { File.Delete(SegFile); } } // Order can be random, must sort. SegDone = SegDone.OrderBy(s => s.Start).ToList(); } // Get script total frames and calculate the work left. TaskCount.Wait(); if (settings.CompletionStatus == CompletionStatus.Cancelled) { SegDone.Clear(); } else { // Create list of segments left. TotalFrames = TaskCount.Result; long SegPos = 0; foreach (SegmentInfo segd in SegDone) { if (segd.Start > SegPos) { SegLeft.Add(new SegmentInfo(SegPos, segd.Start - 1)); } SegPos = segd.End + 1; } if (SegPos < TotalFrames) { SegLeft.Add(new SegmentInfo(SegPos, TotalFrames - 1)); } if (settings.ParallelProcessing > 1) { // Divide in segments int Instances = settings.ParallelProcessing; int SmallSegSize = SegSize / Instances; int StartSegSize = ((Instances - 1) * Instances / 2) * SmallSegSize; SegmentInfo Seg; int SegCount = 0; long IdealSeg, AvailSeg; // Work on copy because original list will be modified. List <SegmentInfo> SegLeftCopy = SegLeft.ToList(); SegLeft.Clear(); for (int i = 0; i < SegLeftCopy.Count(); i++) { Seg = SegLeftCopy[i]; AvailSeg = Seg.Length; while (AvailSeg > 0) { // Start with smaller segments. IdealSeg = SegCount < Instances ? ++SegCount * SmallSegSize : SegSize; // Split segment only if it is larger than threshold if (AvailSeg > IdealSeg + SmallSegSize) { SegLeft.Add(new SegmentInfo(Seg.Start, Seg.Start + IdealSeg - 1)); Seg.Start += IdealSeg; AvailSeg -= IdealSeg; } else { SegLeft.Add(new SegmentInfo(Seg.Start, Seg.End)); AvailSeg = 0; } } } // If we're still missing segments (for short clips), split using other method. // Create segments to reach the desired amount of threads. int SegMissing = SegLeft.Count > 0 ? Threads - SegLeft.Count() : 0; for (int i = 0; i < SegMissing; i++) { // Find largest segment. int SegMaxIndex = 0; long SegMax = SegLeft[0].Length; for (int j = 1; j < SegLeft.Count(); j++) { if (SegLeft[j].Length > SegMax) { SegMaxIndex = j; SegMax = SegLeft[j].Length; } } // Split largest segment in half. Seg = SegLeft[SegMaxIndex]; if (Seg.Length > 80) // Only split if segment has at least 80 frames (creating segments of 40). { long SegSep = Seg.Start + (Seg.Length - 1) / 2; SegLeft[SegMaxIndex] = new SegmentInfo(Seg.Start, SegSep); SegLeft.Insert(SegMaxIndex + 1, new SegmentInfo(SegSep + 1, Seg.End)); } } } } }