public List <VideoFrameInfo> GetRemappedFramesToDuplicate(VideoFrameSection videoFrameSection) { // Merge the frame lists List <VideoFrameInfoWithProcessType> mergeList = videoFrameSection.FramesToDuplicate.Select( f => new VideoFrameInfoWithProcessType { VideoFrameInfo = f, VideoFrameProcessType = VideoFrameProcessType.Duplicate } ).ToList() .Concat( videoFrameSection.FramesToDelete.Select( f => new VideoFrameInfoWithProcessType { VideoFrameInfo = f, VideoFrameProcessType = VideoFrameProcessType.Delete } ).ToList() ).ToList(); // Sort the merge list by frame number mergeList = mergeList.OrderBy(f => f.VideoFrameInfo.Number).ToList(); // Create new remapped list of duplicate frames List <VideoFrameInfo> remappedFramesToDuplicate = new List <VideoFrameInfo>(); // Frames int framesDeletedSoFar = 0; foreach (var vf in mergeList) { if (vf.VideoFrameProcessType == VideoFrameProcessType.Delete) { // Increase the counter framesDeletedSoFar++; continue; } else if (vf.VideoFrameProcessType == VideoFrameProcessType.Duplicate) { // Remap the frame number // Add it to the remapped list remappedFramesToDuplicate.Add( new VideoFrameInfo { Number = vf.VideoFrameInfo.Number - framesDeletedSoFar, StartTime = vf.VideoFrameInfo.StartTime, Duration = vf.VideoFrameInfo.Duration } ); } } return(remappedFramesToDuplicate); }
private int DeleteFrames(List <VideoFrameInfo> allFrames, VideoFrameSection videoFrameSection, int startFrame, int endFrame, int numberOfFrameToDelete) { // Create a temporary list with only the frame range List <VideoFrameInfo> list = allFrames.Where(f => f.Number >= startFrame && f.Number <= endFrame).ToList(); IOrderedEnumerable <VideoFrameInfo> orderedList; // if the list is CFR then sort by frame numer, else by frame difference if (list.IsCFR()) { // Sort the first cutFrames by frame number orderedList = list.OrderBy(f => f.Number); //list.Sort(VideoFrameList.SortType.ByFrameNumber, VideoFrameList.SortOrder.Ascending); } else { // Sort all frames by difference orderedList = list.OrderBy(f => f.DifferencePercentageFromPreviousFrame); //list.Sort(VideoFrameList.SortType.ByFrameDifference, VideoFrameList.SortOrder.Ascending); } // Finally sort all the frames by duration orderedList = orderedList.ThenByDescending(f => f.Duration); //list.Sort(VideoFrameList.SortType.ByDuration, VideoFrameList.SortOrder.Descending); // Apply the order to the list list = orderedList.ToList(); // Check if the muber of frames to delete is more than the range of frames if (numberOfFrameToDelete > endFrame - startFrame + 1) { // We have to delete more frames than we have // That means we are going to delete all the frames from the list // which are going to be less than the numberOfFrameToDelete foreach (var vf in list) { videoFrameSection.FramesToDelete.Add(vf); } return(list.Count); } else { // We have to delete less frames than the ones we have // Select the first numberOfFrameToDelete frames from the ordered list for (int i = 0; i < numberOfFrameToDelete; i++) { videoFrameSection.FramesToDelete.Add(list[i]); } return(numberOfFrameToDelete); } }
private void listSections_SelectedIndexChanged(object sender, EventArgs e) { try { //Ensure that selected index is not -1 if (listSections.SelectedIndex > -1) { VideoFrameSection vfs = vfl.FrameSections[listSections.SelectedIndex]; txtSectionName.Text = vfs.SectionName; txtStartFrame.Text = vfs.FrameStart.ToString(); txtEndFrame.Text = vfs.FrameEnd.ToString(); } } catch (Exception ex) { ShowExceptionMessage(ex); } }
private void btnUpdate_Click(object sender, EventArgs e) { try { if (listSections.SelectedIndex > -1) { //Safe keep the old selected index Int32 oldIdx = listSections.SelectedIndex; //Update the section VideoFrameSection vfs = vfl.FrameSections[listSections.SelectedIndex]; vfs.SectionName = txtSectionName.Text; vfs.FrameStart = Convert.ToInt32(txtStartFrame.Text); vfs.FrameEnd = Convert.ToInt32(txtEndFrame.Text); //Refresh the list RefreshSectionList(); //Select the same section listSections.SelectedIndex = oldIdx; } } catch (Exception ex) { ShowExceptionMessage(ex); } }
private void btnAdd_Click(object sender, EventArgs e) { try { //Prepare data for the new section String sName = txtSectionName.Text; Int32 fStart = 0; Int32 fEnd = 0; if (txtStartFrame.Text.Length > 0) { fStart = Int32.Parse(txtStartFrame.Text); } else { throw new Exception("Please provide with a start frame!"); } if (txtEndFrame.Text.Length > 0) { fEnd = Int32.Parse(txtEndFrame.Text); } else { throw new Exception("Please provide with an end frame!"); } //Create the new section VideoFrameSection vfs = new VideoFrameSection(sName, fStart, fEnd); //Add the section to the frame list vfl.AddSection(vfs); //Refresh the section list control RefreshSectionList(); } catch (Exception ex) { ShowExceptionMessage(ex); } }
private void btnStart_Click(object sender, EventArgs e) { try { Boolean useFakeTimecodes = false; if (tabCtrlFiles.SelectedTab == tabPageProject) { //Check if project file is provided if (txtProjectFile.Text == string.Empty) { throw new Exception("Please provide with a project file first!"); } //Open the project file fr.frpf = new FrameRestorationProjectFile(txtProjectFile.Text); txtVideoFile.Text = fr.frpf.VideoFile; txtTimecodesFile.Text = fr.frpf.TimecodesFile; txtAvisynthOutputFile.Text = fr.frpf.AviSynthOutputFile; if (fr.frpf.TimecodesFile == String.Empty) { useFakeTimecodes = true; } else { useFakeTimecodes = fr.frpf.UseFakeTimecodes; } //fr.vidPlayer.OpenVideo(fr.frpf.VideoFile); if (useFakeTimecodes) { //Load fake timecodes fr.frpf.FrameList.CreateFakeTimecodes(fr.vidPlayer.VideoData.Avs.Clip.NumberOfFrames, Convert.ToDecimal(fr.vidPlayer.VideoData.Avs.Clip.Rate)); //Create a new section VideoFrameSection vfs = new VideoFrameSection("Whole_Video", 0, fr.frpf.FrameList.Count - 1); fr.frpf.FrameList.AddSection(vfs); } trackVideo.Maximum = fr.vidPlayer.VideoData.Avs.Clip.NumberOfFrames - 1; trackVideo.Minimum = 0; fr.vidPlayer.GetFrame(0); } else if (tabCtrlFiles.SelectedTab == tabPageFiles) { //Assume new project //Check if video file exists if (!File.Exists(txtVideoFile.Text)) { throw new AcException("Error creating project! The video file provided does not exist!"); } //Check if timecodes exist if (!File.Exists(txtTimecodesFile.Text)) { if (AcMessageBox.Show("Do you want to use fake timecodes?", "No timecodes found!", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes) { useFakeTimecodes = true; } else { throw new AcException("Error creating project! The Timecodes file provided does not exist!"); } } //Create the new project fr.frpf = new FrameRestorationProjectFile(); fr.frpf.UseFakeTimecodes = useFakeTimecodes; //Load the video //fr.vidPlayer.OpenVideo(txtVideoFile.Text); trackVideo.Maximum = fr.vidPlayer.VideoData.Avs.Clip.NumberOfFrames - 1; trackVideo.Minimum = 0; //Check for fake timecodes if (useFakeTimecodes) { //Load fake timecodes fr.frpf.FrameList.CreateFakeTimecodes(fr.vidPlayer.VideoData.Avs.Clip.NumberOfFrames, Convert.ToDecimal(fr.vidPlayer.VideoData.Avs.Clip.Rate)); } else { //Load the timecodes fr.frpf.FrameList.LoadTimecodes(txtTimecodesFile.Text, false, 3); } //Add the section fr.frpf.FrameList.AddSection(new VideoFrameSection("Whole_Video", 0, fr.vidPlayer.VideoData.Avs.Clip.NumberOfFrames - 1)); //Check the validity of timecodes file if (fr.frpf.FrameList.Count == 0) { AcLogger.Log(new AcException("Error creating project! Timecodes file didn't contain any frames!"), AcLogType.FileAndLogger); fr.vidPlayer.Dispose(); return; } //Check that timecodes and video files match if (fr.vidPlayer.VideoData.Avs.Clip.NumberOfFrames != fr.frpf.FrameList.Count) { AcLogger.Log(new AcException("Error creating project! Timecodes file doesn't match video!"), AcLogType.FileAndLogger); fr.vidPlayer.Dispose(); return; } //Update the project data fr.frpf.VideoFile = txtVideoFile.Text; fr.frpf.TimecodesFile = txtTimecodesFile.Text; //Prompt the user for a project file name String filename = ShowSaveFileDialog("Select a project file to save...", "", "*.frproj (Frame Restoration Project)|*.frproj"); if (filename == null) { return; } fr.frpf.ProjectFile = filename; //Create the new project file fr.WriteProject(); txtProjectFile.Text = filename; //Get the first form fr.vidPlayer.GetFrame(0); } //Enable the controls btnDeleteChange.Enabled = true; btnDeleteFrame.Enabled = true; btnDuplicateFrame.Enabled = true; btnPreview.Enabled = true; btnSaveFiles.Enabled = true; btnUpdateProjectProperties.Enabled = true; checkAutoCommit.Enabled = true; checkZoom.Enabled = true; //refresh the list UpdateListChanges(); } catch (Exception ex) { AcLogger.Log(new AcException("Error creating project!", ex), AcLogType.FileAndLogger); Debug.WriteLine(ex.StackTrace); } }
private void btnSyncAss_Click(object sender, EventArgs e) { try { AssParser assP = new AssParser(); assP.ParseASS(txtAssFile.Text); VideoFrameList vfl = _Kienzan.VideoFrames; //Double framerate = AcHelper.ConvertToDouble(Convert.ToString(comTargetFramerate.SelectedItem)); foreach (AssDialogue assD in assP.AssContents) { Decimal timeToDelete = 0m; for (Int32 currentSection = 0; currentSection < vfl.FrameSections.Count; currentSection++) { VideoFrameSection vfs = vfl.FrameSections[currentSection]; Decimal startSection = vfl.FrameList[vfs.FrameStart].FrameStartTime; Decimal endSection = vfl.FrameList[vfs.FrameEnd].FrameEndTime; //Check if the sub ends before the section if (assD.time_end_double <= startSection) { assD.deleted = true; break; } //Check if the sub starts after the section if (assD.time_start_double >= endSection) { //If its the last sections, then delete the sub if (currentSection == vfl.FrameSections.Count - 1) { assD.deleted = true; break; } else { if (currentSection == 0) { timeToDelete = startSection; } else { Decimal start = startSection; Decimal end = endSection; Decimal prevEnd = vfl.FrameList[vfl.FrameSections[currentSection - 1].FrameEnd].FrameEndTime; timeToDelete += start - prevEnd; } continue; } } //Time to resync the sub if (currentSection == 0) { TimeSpan ts; timeToDelete = startSection; assD.time_start_double = assD.time_start_double - timeToDelete; ts = TimeSpan.FromMilliseconds(Convert.ToDouble(assD.time_start_double)); assD.time_start = ts.Hours.ToString("0") + ":" + ts.Minutes.ToString("00") + ":" + ts.Seconds.ToString("00") + "." + ts.Milliseconds.ToString("00"); assD.time_end_double = assD.time_end_double - timeToDelete; ts = TimeSpan.FromMilliseconds(Convert.ToDouble(assD.time_end_double)); assD.time_end = ts.Hours.ToString("0") + ":" + ts.Minutes.ToString("00") + ":" + ts.Seconds.ToString("00") + "." + ts.Milliseconds.ToString("00"); break; } else { TimeSpan ts; Decimal start = startSection; Decimal end = endSection; Decimal prevEnd = vfl.FrameList[vfl.FrameSections[currentSection - 1].FrameEnd].FrameEndTime; timeToDelete += start - prevEnd; assD.time_start_double = assD.time_start_double - timeToDelete; ts = TimeSpan.FromMilliseconds(Convert.ToDouble(assD.time_start_double)); assD.time_start = ts.Hours.ToString("0") + ":" + ts.Minutes.ToString("00") + ":" + ts.Seconds.ToString("00") + "." + (ts.Milliseconds / 10).ToString("00"); assD.time_end_double = assD.time_end_double - timeToDelete; ts = TimeSpan.FromMilliseconds(Convert.ToDouble(assD.time_end_double)); assD.time_end = ts.Hours.ToString("0") + ":" + ts.Minutes.ToString("00") + ":" + ts.Seconds.ToString("00") + "." + (ts.Milliseconds / 10).ToString("00"); break; } } } assP.WriteFinalAss(txtAssFile.Text.Substring(0, txtAssFile.Text.LastIndexOf(".")) + ".resync.ass"); ShowSuccessMessage("Resync complete!"); } catch (Exception ex) { ShowExceptionMessage(ex); } }
private string KienzanString(VideoFrameSection videoFrameSection) { // Create the string builder StringBuilder sb = new StringBuilder(); // Write the comment line for the section sb.AppendFormat("#{0} FramesDeleted : {1} FramesDuplicated : {2}", videoFrameSection.Name, videoFrameSection.FramesToDelete.Count, videoFrameSection.FramesToDuplicate.Count); sb.AppendLine(); // Write the first trim sb.AppendFormat("{0} = trim(0, {1})", videoFrameSection.Name, videoFrameSection.EndFrameNumber); sb.AppendLine(); // Write the delete frames (if any) if (videoFrameSection.FramesToDelete.Any()) { // Ensure sorted list by frame number // Descending sorting order to avoid clumsy remapping later var framesToDeleteOrdered = videoFrameSection.FramesToDelete.OrderByDescending(f => f.Number); // Create counter int numberOfFramesDeleted = 0; // Write filter first sb.AppendFormat("{0} = DeleteFrame({0}", videoFrameSection.Name); foreach (var vf in framesToDeleteOrdered) { // Check if we already appended 900 frames (AviSynth limitation) if (numberOfFramesDeleted == 900) { // Close the previous filter sb.AppendLine(")"); // Begin a new one sb.AppendFormat("{0} = DeleteFrame({0}", videoFrameSection.Name); // Write the frame number sb.AppendFormat(", {0}", vf.Number); // Reset the counter numberOfFramesDeleted = 1; } else { // Write the frame number sb.AppendFormat(", {0}", vf.Number); // Increase the counter numberOfFramesDeleted++; } } // Close the last filter sb.AppendLine(")"); } // Write the remapped duplicate frames (if any) if (videoFrameSection.FramesToDuplicate.Any()) { // Create new remapped list of duplicate frames // First Delete the frames // So remap the frames to duplicate var remappedFramesToDuplicate = GetRemappedFramesToDuplicate(videoFrameSection); // Ensure sorted list by frame number // Descending sorting order to avoid clumsy remapping later remappedFramesToDuplicate = remappedFramesToDuplicate.OrderByDescending(f => f.Number).ToList(); // Create counter int numberOfFramesDuplicated = 0; // Write filter first sb.AppendFormat("{0} = DuplicateFrame({0}", videoFrameSection.Name); foreach (var vf in remappedFramesToDuplicate) { // Check if we already appended 900 frames (AviSynth limitation) if (numberOfFramesDuplicated == 900) { // Close the previous filter sb.AppendLine(")"); // Begin a new one sb.AppendFormat("{0} = DuplicateFrame({0}", videoFrameSection.Name); // Write the frame number sb.AppendFormat(", {0}", vf.Number); // Reset the counter numberOfFramesDuplicated = 1; } else { // Write the frame number sb.AppendFormat(", {0}", vf.Number); // Increase the counter numberOfFramesDuplicated++; } } // Close the last filter sb.AppendLine(")"); } // If section starts from the first video frame (framestart = 0) then there is no reason for the final trim if (videoFrameSection.StartFrameNumber > 0) { // Write the final trim sb.AppendFormat("{0} = trim({0}, {1}, 0)", videoFrameSection.Name, videoFrameSection.StartFrameNumber); sb.AppendLine(); } return(sb.ToString()); }
private void btnSplit_Click(object sender, EventArgs e) { try { AssParser assP = new AssParser(); assP.ParseASS(txtAssFile.Text); VideoFrameList vfl = new VideoFrameList(); SectionParser.ParseSections(txtSectionsFile.Text, vfl); Decimal framerate = AcHelper.DecimalParse(txtFramerate.Text); foreach (AssDialogue assD in assP.AssContents) { Decimal timeToDelete = 0; for (Int32 currentSection = 0; currentSection < vfl.FrameSections.Count; currentSection++) { VideoFrameSection vfs = vfl.FrameSections[currentSection]; Decimal startSection = VideoFrame.GetStartTimeFromFrameNumber(vfs.FrameStart, framerate); Decimal endSection = VideoFrame.GetStartTimeFromFrameNumber(vfs.FrameEnd, framerate); //Check if the sub ends before the section if (assD.time_end_double <= startSection) { assD.deleted = true; break; } //Check if the sub starts after the section if (assD.time_start_double >= endSection) { //If its the last sections, then delete the sub if (currentSection == vfl.FrameSections.Count - 1) { assD.deleted = true; break; } else { continue; } } //Time to resync the sub if (currentSection == 0) { TimeSpan ts; timeToDelete = startSection; assD.time_start_double = assD.time_start_double - timeToDelete; ts = TimeSpan.FromMilliseconds(Convert.ToDouble(assD.time_start_double)); assD.time_start = ts.Hours.ToString("0") + ":" + ts.Minutes.ToString("00") + ":" + ts.Seconds.ToString("00") + "." + ts.Milliseconds.ToString("00"); assD.time_end_double = assD.time_end_double - timeToDelete; ts = TimeSpan.FromMilliseconds(Convert.ToDouble(assD.time_end_double)); assD.time_end = ts.Hours.ToString("0") + ":" + ts.Minutes.ToString("00") + ":" + ts.Seconds.ToString("00") + "." + ts.Milliseconds.ToString("00"); break; } else { TimeSpan ts; Decimal start = startSection; Decimal end = endSection; Decimal prevEnd = VideoFrame.GetStartTimeFromFrameNumber(vfl.FrameSections[currentSection - 1].FrameEnd, framerate); timeToDelete += start - prevEnd - VideoFrame.GetDurationFromFrameRate(framerate); assD.time_start_double = assD.time_start_double - timeToDelete; ts = TimeSpan.FromMilliseconds(Convert.ToDouble(assD.time_start_double)); assD.time_start = ts.Hours.ToString("0") + ":" + ts.Minutes.ToString("00") + ":" + ts.Seconds.ToString("00") + "." + ts.Milliseconds.ToString("00"); assD.time_end_double = assD.time_end_double - timeToDelete; ts = TimeSpan.FromMilliseconds(Convert.ToDouble(assD.time_end_double)); assD.time_end = ts.Hours.ToString("0") + ":" + ts.Minutes.ToString("00") + ":" + ts.Seconds.ToString("00") + "." + ts.Milliseconds.ToString("00"); break; } } } assP.WriteFinalAss(txtAssFile.Text.Substring(0, txtAssFile.Text.LastIndexOf(".") - 1) + ".resync.ass"); MessageBox.Show("Resync complete!", "Success!"); } catch (Exception ex) { MessageBox.Show(ex.Message, "Error!"); } }
/// <summary> /// Function to parse the trims file /// </summary> /// <param name="sectionsFile"> /// String with the path of the trims file /// </param> public static void ParseSections(String sectionsFile, VideoFrameList vfl) { StreamReader sr; String line = ""; try { //Open trims file sr = new StreamReader(sectionsFile, Encoding.UTF8); } catch (Exception ex) { throw (new AcException("Error opening trims file!", ex)); } try { //Read file while ((line = sr.ReadLine()) != null) { //Check for Avisynth style trims if (line.ToLowerInvariant().Contains("trim") && !(line.StartsWith("#"))) { String tmp = line.ToLowerInvariant().Substring(line.IndexOf("trim", StringComparison.InvariantCultureIgnoreCase)); tmp = tmp.ToLowerInvariant().Substring(tmp.IndexOf("(") + 1); tmp = tmp.Substring(0, tmp.IndexOf(")")); tmp = tmp.Trim(); VideoFrameSection vfsTmp = new VideoFrameSection(); if (line.Contains("=")) { vfsTmp.SectionName = line.Substring(0, line.IndexOf("=")).Trim(); } String[] elements = tmp.Split(new String[] { "," }, StringSplitOptions.None); //Check trim's form //1. trim(clip,start,end) //2. trim(start,end) if (elements.Length == 3) { vfsTmp.FrameStart = Convert.ToInt32(elements[1].Trim()); vfsTmp.FrameEnd = Convert.ToInt32(elements[2].Trim()); vfl.FrameSections.Add(vfsTmp); } else if (elements.Length == 2) { vfsTmp.FrameStart = Convert.ToInt32(elements[0].Trim()); vfsTmp.FrameEnd = Convert.ToInt32(elements[1].Trim()); vfl.FrameSections.Add(vfsTmp); } else { //No valid format found, write to debug //AcLogger.Log(new AcException("Invalid Trim format!"), AcLogger.AcLogType.Form); } } //Check for simple text trims else if (line.Contains(",") || line.Contains("-")) { try { //Check if starts with number Int32 chkTmp = 0; if (Int32.TryParse(line.Substring(0, 1), out chkTmp)) { //if starts with number check if it contains comments (#) if (line.Contains("#")) { line = line.Substring(0, line.IndexOf("#")); line = line.Trim(); } VideoFrameSection vfsTmp = new VideoFrameSection(); String[] elements = new String[] { "" }; if (line.Contains(",")) { elements = line.Split(new String[] { "," }, StringSplitOptions.None); } else if (line.Contains("-")) { elements = line.Split(new String[] { "-" }, StringSplitOptions.None); } //Check trim's form //1. trim(clip,start,end) //2. trim(start,end) if (elements.Length == 3) { vfsTmp.FrameStart = Convert.ToInt32(elements[1].Trim()); vfsTmp.FrameEnd = Convert.ToInt32(elements[2].Trim()); vfl.FrameSections.Add(vfsTmp); } else if (elements.Length == 2) { vfsTmp.FrameStart = Convert.ToInt32(elements[0].Trim()); vfsTmp.FrameEnd = Convert.ToInt32(elements[1].Trim()); vfl.FrameSections.Add(vfsTmp); } else { //No valid format found, write to debug //AcLogger.Log(new AcException("Invalid Trim format!"), AcLogger.AcLogType.Form); } } } catch (Exception ex) { Debug.WriteLine(ex); //No valid format found, write to debug //AcLogger.Log(new AcException("Invalid Trim format!", ex), AcLogger.AcLogType.Form); } } } } catch (Exception ex) { sr.Close(); throw (new AcException("Error in reading trims file!", ex)); } try { //Close File sr.Close(); } catch (Exception ex) { throw (new AcException("Error in closing trims file!", ex)); } }