public static bool CheckForUnsupportedCodecs(MuxPath x) { for (int i = 0; i < x.Length; i++) { foreach (MuxableType type in x[i].handledInputTypes) { for (int j = i; j < x.Length; j++) { if (type.codec is VideoCodec) { if (!x[j].muxerInterface.SupportsVideoCodec((VideoCodec)type.codec)) { return(true); } } else if (type.codec is AudioCodec) { if (!x[j].muxerInterface.SupportsAudioCodec((AudioCodec)type.codec)) { return(true); } } } } } return(false); }
public MuxPath Clone() { MuxPath nMuxPath = new MuxPath(initialInputTypes, targetType); nMuxPath.path.AddRange(path); return(nMuxPath); }
/// <summary> /// Finds the shortest mux path for a given set of input MuxableTypes (ie the /// encoder output types have all already been chosen here). /// </summary> /// Initial stage: if currentMuxPath is empty, it creates a first leg. /// Recursive step: It tries out adding all possible muxers to the current mux path, /// and calls itself with this extended mux path. It returns the shortest path. /// Final step: This will stop recursing if there are no muxers that can help, or if a muxer /// is found in one step that finalizes the path. This is guaranteed to finish: /// if no progress is made, then it will not recurse. Otherwise, there is a finite /// amount of progress (progress is the number of streams muxed), so it will eventually /// stop progressing. /// <param name="currentMuxPath">Current mux path to be worked on</param> /// <param name="unhandledDesiredInputTypes">What remains to be muxed</param> /// <param name="desiredContainerType">Container type we are aiming at</param> /// <returns></returns> private MuxPath getShortestMuxPath(MuxPath currentMuxPath, List <MuxableType> unhandledDesiredInputTypes, ContainerType desiredContainerType) { if (currentMuxPath.IsCompleted()) { return(currentMuxPath); } List <MuxableType> handledInputTypes; List <MuxableType> unhandledInputTypes; List <MuxPath> allMuxPaths = new List <MuxPath>(); foreach (IMuxing muxer in mainForm.PackageSystem.MuxerProviders.Values) { ProcessingLevel level; if (currentMuxPath.Length > 0) { level = muxer.CanBeProcessed( currentMuxPath[currentMuxPath.Length - 1].muxerInterface.GetSupportedContainerTypes().ToArray(), unhandledDesiredInputTypes.ToArray(), out handledInputTypes, out unhandledInputTypes); } else { level = muxer.CanBeProcessed(unhandledDesiredInputTypes.ToArray(), out handledInputTypes, out unhandledInputTypes); } if (level != ProcessingLevel.NONE) { MuxPath newMuxPath = currentMuxPath.Clone(); MuxPathLeg currentMPL = new MuxPathLeg(); currentMPL.muxerInterface = muxer; currentMPL.handledInputTypes = handledInputTypes; currentMPL.unhandledInputTypes = unhandledInputTypes; newMuxPath.Add(currentMPL); if (unhandledInputTypes.Count == 0) { // All the streams have been muxed into some file. Now let's // just make sure that we can convert this file to the format we want // (or leave it alone if it already is in that format). List <IMuxing> allMuxers = new List <IMuxing>(); allMuxers.AddRange(mainForm.PackageSystem.MuxerProviders.Values); MuxPath shortestPath = getShortestMuxPath(newMuxPath, allMuxers, desiredContainerType); if (shortestPath != null) { allMuxPaths.Add(shortestPath); } } MuxPath aShortestPath = getShortestMuxPath(currentMuxPath, muxer, new List <MuxableType>(), handledInputTypes, unhandledInputTypes, desiredContainerType); if (aShortestPath != null) { allMuxPaths.Add(aShortestPath); } } } return(comparer.GetBestMuxPath(allMuxPaths)); }
/// <summary> /// Finds the best mux path /// </summary> /// <param name="containerType"></param> /// <param name="allTypes"></param> /// <returns></returns> public MuxPath GetMuxPath(ContainerType containerType, bool alwaysMux, params MuxableType[] allTypes) { List <MuxableType> inputTypes = new List <MuxableType>(); inputTypes.AddRange(allTypes); MuxPath shortestPath = getShortestMuxPath(new MuxPath(inputTypes, containerType, alwaysMux), inputTypes, containerType); return(shortestPath); }
/// <summary> /// Recurses to find the shortest mux path. /// </summary> /// Initial stage: if currentMuxPath is empty, it creates a first leg. /// Recursive step: It tries out adding all possible muxers to the current mux path, /// and calls itself with this extended mux path. It returns the shortest path. /// Final step: This will stop recursing if there are no muxers that can help, or if a muxer /// is found in one step that finalizes the path. This is guaranteed to finish: /// if no progress is made, then it will not recurse. Otherwise, there is a finite /// amount of progress (progress is the number of streams muxed), so it will eventually /// stop progressing. /// <param name="currentMuxPath">Current mux path to be worked on</param> /// <param name="unhandledDesiredInputTypes">What remains to be muxed</param> /// <param name="desiredContainerType">Container type we are aiming at</param> /// <returns></returns> private MuxPath getShortestMuxPath(MuxPath currentMuxPath, List <MuxableType> unhandledDesiredInputTypes, ContainerType desiredContainerType) { List <MuxableType> handledInputTypes = new List <MuxableType>(); List <MuxableType> unhandledInputTypes = new List <MuxableType>(); List <MuxPath> allMuxPaths = new List <MuxPath>(); if (currentMuxPath.IsCompleted()) { return(currentMuxPath); } foreach (IMuxing muxer in mainForm.PackageSystem.MuxerProviders.Values) { ProcessingLevel level; if (currentMuxPath.Length > 0) { level = muxer.CanBeProcessed( currentMuxPath[currentMuxPath.Length - 1].muxerInterface.GetSupportedContainerTypes().ToArray(), unhandledDesiredInputTypes.ToArray(), out handledInputTypes, out unhandledInputTypes); } else { level = muxer.CanBeProcessed(unhandledDesiredInputTypes.ToArray(), out handledInputTypes, out unhandledInputTypes); } if (level != ProcessingLevel.NONE) { MuxPath newMuxPath = currentMuxPath.Clone(); MuxPathLeg currentMPL = new MuxPathLeg(); currentMPL.muxerInterface = muxer; currentMPL.handledInputTypes = handledInputTypes; currentMPL.unhandledInputTypes = unhandledInputTypes; newMuxPath.Add(currentMPL); if (unhandledInputTypes.Count == 0) { List <IMuxing> allMuxers = new List <IMuxing>(); allMuxers.AddRange(mainForm.PackageSystem.MuxerProviders.Values); MuxPath shortestPath = getShortestMuxPath(newMuxPath, allMuxers, desiredContainerType); if (shortestPath != null) { allMuxPaths.Add(shortestPath); } } MuxPath aShortestPath = getShortestMuxPath(currentMuxPath, muxer, new List <MuxableType>(), handledInputTypes, unhandledInputTypes, desiredContainerType); if (aShortestPath != null) { allMuxPaths.Add(aShortestPath); } } } return(comparer.GetBestMuxPath(allMuxPaths)); }
public bool CanBeMuxed(ContainerType containerType, params MuxableType[] allTypes) { MuxPath muxPath = GetMuxPath(containerType, false, allTypes); if (muxPath != null) { return(true); } else { return(false); } }
/// <summary> /// Checks if this mux path is invalid, according to any of the checkers registered. /// </summary> /// <param name="path"></param> /// <returns>false if valid or no checkers found, true if invalid.</returns> bool BadMuxPath(MuxPath path) { lock (this) { foreach (CheckMuxPath checker in checkingMethods) { if (checker(path)) { return(true); } } return(false); } }
public bool CanBeMuxed(VideoEncoderType codec, AudioEncoderType[] audioCodecs, ContainerType containerType, params MuxableType[] decidedTypes) { MuxPath muxPath = GetMuxPath(codec, audioCodecs, containerType, decidedTypes); if (muxPath != null) { return(true); } else { return(false); } }
/// <summary> /// Checks whether a mux path for AVC-in-MKV uses VFW-based storage (which is bad). /// </summary> /// <param name="x"></param> /// <returns>true if VFW storage is found</returns> public static bool CheckForVFWMatroska(MuxPath x) { if (x.TargetType != ContainerType.MKV) { return(false); } foreach (MuxPathLeg mpl in x) { /* if (mpl.muxerInterface is AVC2AVIMuxerProvider) * { * return true; * }*/ } return(false); }
/// <summary> /// Finds the best mux path if some of the inputs have not yet been /// produced (they are yet to be encoded). When this is the case, /// there is more flexibility, as some encoders can produce outputs /// in multiple formats. This function suggests the output formats /// they should produce as well as the mux path. /// </summary> /// <param name="undecidedInputs">List of encoder types for the inputs which have not yet been encoded</param> /// <param name="decidedInputs">List of file types for the inputs which are already encoded</param> /// <param name="containerType">Target container type</param> /// <returns></returns> private MuxPath findBestMuxPathAndConfig(List <IEncoderType> undecidedInputs, List <MuxableType> decidedInputs, ContainerType containerType) { if (undecidedInputs.Count == 0) { return(getShortestMuxPath(new MuxPath(decidedInputs, containerType), decidedInputs, containerType)); } else { List <MuxPath> allPaths = new List <MuxPath>(); IEncoderType undecidedInput = undecidedInputs[0]; undecidedInputs.RemoveAt(0); if (undecidedInput is VideoEncoderType) { VideoType[] allTypes = vProvider.GetSupportedOutput((VideoEncoderType)undecidedInput); foreach (VideoType v in allTypes) { MuxableType input = new MuxableType(v, undecidedInput.Codec); decidedInputs.Add(input); MuxPath path = findBestMuxPathAndConfig(undecidedInputs, decidedInputs, containerType); if (path != null) { allPaths.Add(path); } decidedInputs.Remove(input); } } if (undecidedInput is AudioEncoderType) { AudioType[] allTypes = aProvider.GetSupportedOutput((AudioEncoderType)undecidedInput); foreach (AudioType a in allTypes) { MuxableType input = new MuxableType(a, undecidedInput.Codec); decidedInputs.Add(input); MuxPath path = findBestMuxPathAndConfig(undecidedInputs, decidedInputs, containerType); if (path != null) { allPaths.Add(path); } decidedInputs.Remove(input); } } undecidedInputs.Insert(0, undecidedInput); return(comparer.GetBestMuxPath(allPaths)); } }
/// <summary> /// Step in the recursive stage which chooses, of all the MuxableTypes which /// *could* be handled, whether they should be. That means, it generates a /// mux path which involves muxing in each of the 2^n combinations of inputs /// at this stage. /// /// I'm not sure if this step is actually necessary. The only possible /// use I can think of is if you have a specific muxpath rule which says /// that only one file can be muxed in at a time, or only some specific /// combination of files can be muxed in at a time. /// -- berrinam /// </summary> /// <param name="currentMuxPath"></param> /// <param name="muxer"></param> /// <param name="decidedHandledTypes"></param> /// <param name="undecidedPossibleHandledTypes"></param> /// <param name="unhandledInputTypes"></param> /// <param name="desiredContainerType"></param> /// <returns></returns> private MuxPath getShortestMuxPath(MuxPath currentMuxPath, IMuxing muxer, List <MuxableType> decidedHandledTypes, List <MuxableType> undecidedPossibleHandledTypes, List <MuxableType> unhandledInputTypes, ContainerType desiredContainerType) { if (undecidedPossibleHandledTypes.Count == 0) { MuxPathLeg mpl = new MuxPathLeg(); mpl.muxerInterface = muxer; mpl.handledInputTypes = new List <MuxableType>(decidedHandledTypes); mpl.unhandledInputTypes = new List <MuxableType>(unhandledInputTypes); MuxPath newMuxPath = currentMuxPath.Clone(); newMuxPath.Add(mpl); if (decidedHandledTypes.Count == 0) { return(null); } return(getShortestMuxPath(newMuxPath, unhandledInputTypes, desiredContainerType)); } else { List <MuxPath> allMuxPaths = new List <MuxPath>(); MuxableType type = undecidedPossibleHandledTypes[0]; undecidedPossibleHandledTypes.RemoveAt(0); decidedHandledTypes.Add(type); MuxPath shortestMuxPath = getShortestMuxPath(currentMuxPath, muxer, decidedHandledTypes, undecidedPossibleHandledTypes, unhandledInputTypes, desiredContainerType); if (shortestMuxPath != null) { allMuxPaths.Add(shortestMuxPath); } decidedHandledTypes.Remove(type); unhandledInputTypes.Add(type); shortestMuxPath = getShortestMuxPath(currentMuxPath, muxer, decidedHandledTypes, undecidedPossibleHandledTypes, unhandledInputTypes, desiredContainerType); if (shortestMuxPath != null) { allMuxPaths.Add(shortestMuxPath); } unhandledInputTypes.Remove(type); undecidedPossibleHandledTypes.Add(type); return(comparer.GetBestMuxPath(allMuxPaths)); } }
private void fixFileNameExtensions(VideoStream video, AudioJob[] audioStreams, ContainerType container) { AudioEncoderType[] audioCodecs = new AudioEncoderType[audioStreams.Length]; for (int i = 0; i < audioStreams.Length; i++) { audioCodecs[i] = audioStreams[i].Settings.EncoderType; } MuxPath path = mainForm.MuxProvider.GetMuxPath(video.Settings.EncoderType, audioCodecs, container); if (path == null) { return; } List <AudioType> audioTypes = new List <AudioType>(); foreach (MuxableType type in path.InitialInputTypes) { if (type.outputType is VideoType) { video.Output = Path.ChangeExtension(video.Output, type.outputType.Extension); video.VideoType = type; } if (type.outputType is AudioType) { audioTypes.Add((AudioType)type.outputType); } } AudioEncoderProvider aProvider = new AudioEncoderProvider(); for (int i = 0; i < audioStreams.Length; i++) { AudioType[] types = aProvider.GetSupportedOutput(audioStreams[i].Settings.EncoderType); foreach (AudioType type in types) { if (audioTypes.Contains(type)) { audioStreams[i].Output = Path.ChangeExtension(audioStreams[i].Output, type.Extension); break; } } } }
/// <summary> /// Compares x to y by counting the number of raw AAC files that are input. Fewer is better, /// because the muxers can't pick up whether SBR is signalled if it is in raw aac format /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public static int CompareByAACContainer(MuxPath x, MuxPath y) { int xInitialRawAAC = 0, yInitialRawAAC = 0; foreach (MuxableType initialType in x.InitialInputTypes) { if (initialType.outputType.Equals(AudioType.RAWAAC)) { xInitialRawAAC++; } } foreach (MuxableType initialType in y.InitialInputTypes) { if (initialType.outputType.Equals(AudioType.RAWAAC)) { yInitialRawAAC++; } } return(xInitialRawAAC - yInitialRawAAC); }
/// <summary> /// Returns the result of the comparison of the two mux paths according to all the registered muxcomparers /// </summary> /// <param name="x">The first mux path to compare</param> /// <param name="y">The second mux path to compare</param> /// <returns>Negative if x is better, positive if y is better, 0 if equally good.</returns> int Compare(MuxPath x, MuxPath y) { lock (this) { if (!comparisonSorted) { comparisonMethods.Sort(Compare); comparisonSorted = true; } foreach (PreferencedComparer comparer in comparisonMethods) { int result = comparer.method(x, y); if (result != 0) { return(result); } } return(0); } }
/// <summary> /// Given a mux path in which all the inputs have already been handled, /// this finds the shortest mux path to achieve the desired container type. /// </summary> /// <param name="currentMuxPath"></param> /// <param name="remainingMuxers">List of muxers which haven't yet been used /// in this final stage. There's no point having a muxer twice in this final /// stage, as the output of the second time could substitute the output of /// the first time.</param> /// <param name="desiredContainerType"></param> /// <returns></returns> private MuxPath getShortestMuxPath(MuxPath currentMuxPath, List <IMuxing> remainingMuxers, ContainerType desiredContainerType) { if (currentMuxPath.IsCompleted()) { return(currentMuxPath); } List <MuxPath> allMuxPaths = new List <MuxPath>(); List <IMuxing> newRemainingMuxers = new List <IMuxing>(); newRemainingMuxers.AddRange(remainingMuxers); foreach (IMuxing muxer in remainingMuxers) { bool supportsInput = currentMuxPath[currentMuxPath.Length - 1].muxerInterface.GetContainersInCommon(muxer).Count > 0; if (!supportsInput) { continue; } MuxPath newMuxPath = currentMuxPath.Clone(); MuxPathLeg currentMPL = new MuxPathLeg(); currentMPL.muxerInterface = muxer; currentMPL.handledInputTypes = new List <MuxableType>(); currentMPL.unhandledInputTypes = new List <MuxableType>(); newMuxPath.Add(currentMPL); newRemainingMuxers.Remove(muxer); MuxPath shortestPath = getShortestMuxPath(newMuxPath, newRemainingMuxers, desiredContainerType); if (shortestPath != null) { allMuxPaths.Add(shortestPath); } newRemainingMuxers.Add(muxer); } return(comparer.GetBestMuxPath(allMuxPaths)); }
public MuxPath Clone() { MuxPath nMuxPath = new MuxPath(initialInputTypes, targetType); nMuxPath.path.AddRange(path); return nMuxPath; }
/// <summary> /// Checks whether a mux path for AVC-in-MKV uses VFW-based storage (which is bad). /// </summary> /// <param name="x"></param> /// <returns>true if VFW storage is found</returns> public static bool CheckForVFWMatroska(MuxPath x) { if (x.TargetType != ContainerType.MKV) return false; foreach (MuxPathLeg mpl in x) { /* if (mpl.muxerInterface is AVC2AVIMuxerProvider) { return true; }*/ } return false; }
/// <summary> /// Compares x to y by counting the number of raw AAC files that are input. Fewer is better, /// because the muxers can't pick up whether SBR is signalled if it is in raw aac format /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public static int CompareByAACContainer(MuxPath x, MuxPath y) { int xInitialRawAAC = 0, yInitialRawAAC = 0; foreach (MuxableType initialType in x.InitialInputTypes) { if (initialType.outputType.Equals(AudioType.RAWAAC)) xInitialRawAAC++; } foreach (MuxableType initialType in y.InitialInputTypes) { if (initialType.outputType.Equals(AudioType.RAWAAC)) yInitialRawAAC++; } return xInitialRawAAC - yInitialRawAAC; }
/// <summary> /// The most primitive comparison method. Says the shorter ones are better /// </summary> /// <param name="x">The first mux path</param> /// <param name="y">The second mux path</param> /// <returns>x.Length - y.Length</returns> public static int CompareByLength(MuxPath x, MuxPath y) { return x.Length - y.Length; }
/// <summary> /// The most primitive comparison method. Says the shorter ones are better /// </summary> /// <param name="x">The first mux path</param> /// <param name="y">The second mux path</param> /// <returns>x.Length - y.Length</returns> public static int CompareByLength(MuxPath x, MuxPath y) { return(x.Length - y.Length); }
/// <summary> /// Checks if this mux path is invalid, according to any of the checkers registered. /// </summary> /// <param name="path"></param> /// <returns>false if valid or no checkers found, true if invalid.</returns> bool BadMuxPath(MuxPath path) { lock (this) { foreach (CheckMuxPath checker in checkingMethods) { if (checker(path)) return true; } return false; } }
/// <summary> /// Returns the result of the comparison of the two mux paths according to all the registered muxcomparers /// </summary> /// <param name="x">The first mux path to compare</param> /// <param name="y">The second mux path to compare</param> /// <returns>Negative if x is better, positive if y is better, 0 if equally good.</returns> int Compare(MuxPath x, MuxPath y) { lock (this) { if (!comparisonSorted) { comparisonMethods.Sort(Compare); comparisonSorted = true; } foreach (PreferencedComparer comparer in comparisonMethods) { int result = comparer.method(x, y); if (result != 0) return result; } return 0; } }
public static bool CheckForUnsupportedCodecs(MuxPath x) { for (int i = 0; i < x.Length; i++) { foreach (MuxableType type in x[i].handledInputTypes) { for (int j = i; j < x.Length; j++) { if (type.codec is VideoCodec) { if (!x[j].muxerInterface.SupportsVideoCodec((VideoCodec)type.codec)) return true; } else if (type.codec is AudioCodec) { if (!x[j].muxerInterface.SupportsAudioCodec((AudioCodec)type.codec)) return true; } } } } return false; }
public JobChain GenerateMuxJobs(VideoStream video, decimal?framerate, MuxStream[] audioStreamsArray, MuxableType[] audioTypes, MuxStream[] subtitleStreamsArray, MuxableType[] subTypes, string chapterFile, MuxableType chapterInputType, ContainerType container, string output, FileSize?splitSize, List <string> inputsToDelete, string deviceType, MuxableType deviceOutputType, bool alwaysMuxOutput) { Debug.Assert(splitSize == null || splitSize.Value != FileSize.Empty); MuxProvider prov = mainForm.MuxProvider; List <MuxableType> allTypes = new List <MuxableType>(); List <MuxableType> tempTypes = new List <MuxableType>(); List <MuxableType> duplicateTypes = new List <MuxableType>(); tempTypes.AddRange(audioTypes); tempTypes.AddRange(subTypes); allTypes.Add(video.VideoType); // remove duplicate entries to speed up the process foreach (MuxableType oType in tempTypes) { bool bFound = false; foreach (MuxableType oAllType in allTypes) { if (oType.outputType.ID.Equals(oAllType.outputType.ID)) { bFound = true; break; } } if (!bFound) { allTypes.Add(oType); } else { duplicateTypes.Add(oType); } } if (chapterInputType != null) { allTypes.Add(chapterInputType); } if (deviceOutputType != null) { allTypes.Add(deviceOutputType); } // get mux path MuxPath muxPath = prov.GetMuxPath(container, alwaysMuxOutput || splitSize.HasValue, allTypes.ToArray()); // add duplicate entries back into the mux path muxPath.InitialInputTypes.AddRange(duplicateTypes); while (duplicateTypes.Count > 0) { int iPath = 0; for (int i = 0; i < muxPath.Length; i++) { foreach (MuxableType oType in muxPath[i].handledInputTypes) { if (oType.outputType.ID.Equals(duplicateTypes[0].outputType.ID)) { iPath = i; } } } muxPath[iPath].handledInputTypes.Add(duplicateTypes[0]); duplicateTypes.RemoveAt(0); } List <MuxJob> jobs = new List <MuxJob>(); List <MuxStream> subtitleStreams = new List <MuxStream>(subtitleStreamsArray); List <MuxStream> audioStreams = new List <MuxStream>(audioStreamsArray); int index = 0; int tempNumber = 1; string previousOutput = null; foreach (MuxPathLeg mpl in muxPath) { List <string> filesToDeleteThisJob = new List <string>(); MuxJob mjob = new MuxJob(); if (previousOutput != null) { mjob.Settings.MuxedInput = previousOutput; filesToDeleteThisJob.Add(previousOutput); } if (video.Settings != null) { mjob.NbOfBFrames = video.Settings.NbBframes; mjob.Codec = video.Settings.Codec.ToString(); mjob.Settings.VideoName = video.Settings.VideoName; } mjob.NbOfFrames = video.NumberOfFrames; string fpsFormated = String.Format("{0:##.###}", framerate); // this formating is required for mkvmerge at least to avoid fps rounding error mjob.Settings.Framerate = Convert.ToDecimal(fpsFormated); string tempOutputName = Path.Combine(Path.GetDirectoryName(output), Path.GetFileNameWithoutExtension(output) + tempNumber + "."); tempNumber++; foreach (MuxableType o in mpl.handledInputTypes) { if (o.outputType is VideoType) { mjob.Settings.VideoInput = video.Output; if (inputsToDelete.Contains(video.Output)) { filesToDeleteThisJob.Add(video.Output); } mjob.Settings.DAR = video.DAR; } else if (o.outputType is AudioType) { MuxStream stream = audioStreams.Find(delegate(MuxStream m) { return(VideoUtil.guessAudioType(m.path) == o.outputType); }); if (stream != null) { mjob.Settings.AudioStreams.Add(stream); audioStreams.Remove(stream); if (inputsToDelete.Contains(stream.path)) { filesToDeleteThisJob.Add(stream.path); } } } else if (o.outputType is SubtitleType) { MuxStream stream = subtitleStreams.Find(delegate(MuxStream m) { return(VideoUtil.guessSubtitleType(m.path) == o.outputType); }); if (stream != null) { mjob.Settings.SubtitleStreams.Add(stream); subtitleStreams.Remove(stream); if (inputsToDelete.Contains(stream.path)) { filesToDeleteThisJob.Add(stream.path); } } } else if (o.outputType is ChapterType) { if ((VideoUtil.guessChapterType(chapterFile) == o.outputType)) { mjob.Settings.ChapterFile = chapterFile; } if (inputsToDelete.Contains(chapterFile)) { filesToDeleteThisJob.Add(chapterFile); } } else if (o.outputType is DeviceType) { if ((VideoUtil.guessDeviceType(deviceType) == o.outputType)) { mjob.Settings.DeviceType = deviceType; } } } foreach (MuxStream s in mjob.Settings.AudioStreams) { audioStreams.Remove(s); } foreach (MuxStream s in mjob.Settings.SubtitleStreams) { subtitleStreams.Remove(s); } mjob.FilesToDelete.AddRange(filesToDeleteThisJob); if (index == muxPath.Length - 1) { mjob.Settings.MuxedOutput = output; mjob.Settings.SplitSize = splitSize; mjob.Settings.DAR = video.DAR; mjob.ContainerType = container; } else { ContainerType cot = mpl.muxerInterface.GetContainersInCommon(muxPath[index + 1].muxerInterface)[0]; mjob.Settings.MuxedOutput = tempOutputName + cot.Extension; mjob.ContainerType = cot; } previousOutput = mjob.Settings.MuxedOutput; index++; jobs.Add(mjob); if (string.IsNullOrEmpty(mjob.Settings.VideoInput)) { mjob.Input = mjob.Settings.MuxedInput; } else { mjob.Input = mjob.Settings.VideoInput; } mjob.Output = mjob.Settings.MuxedOutput; mjob.MuxType = mpl.muxerInterface.MuxerType; } return(new SequentialChain(jobs.ToArray())); }
public JobChain GenerateMuxJobs(VideoStream video, decimal?framerate, MuxStream[] audioStreamsArray, MuxableType[] audioTypes, MuxStream[] subtitleStreamsArray, MuxableType[] subTypes, string chapterFile, MuxableType chapterInputType, ContainerType container, string output, FileSize?splitSize, List <string> inputsToDelete) { Debug.Assert(splitSize == null || splitSize.Value != FileSize.Empty); MuxProvider prov = mainForm.MuxProvider; List <MuxableType> allTypes = new List <MuxableType>(); allTypes.Add(video.VideoType); allTypes.AddRange(audioTypes); allTypes.AddRange(subTypes); if (chapterInputType != null) { allTypes.Add(chapterInputType); } MuxPath muxPath = prov.GetMuxPath(container, allTypes.ToArray()); List <MuxJob> jobs = new List <MuxJob>(); List <MuxStream> subtitleStreams = new List <MuxStream>(subtitleStreamsArray); List <MuxStream> audioStreams = new List <MuxStream>(audioStreamsArray); int index = 0; int tempNumber = 1; string previousOutput = null; foreach (MuxPathLeg mpl in muxPath) { List <string> filesToDeleteThisJob = new List <string>(); MuxJob mjob = new MuxJob(); if (previousOutput != null) { mjob.Settings.MuxedInput = previousOutput; filesToDeleteThisJob.Add(previousOutput); } mjob.NbOfFrames = video.NumberOfFrames; mjob.NbOfBFrames = video.Settings.NbBframes; mjob.Codec = video.Settings.Codec.ToString(); mjob.Settings.Framerate = framerate; string tempOutputName = Path.Combine(Path.GetDirectoryName(output), Path.GetFileNameWithoutExtension(output) + tempNumber + "."); tempNumber++; foreach (MuxableType o in mpl.handledInputTypes) { if (o.outputType is VideoType) { mjob.Settings.VideoInput = video.Output; if (inputsToDelete.Contains(video.Output)) { filesToDeleteThisJob.Add(video.Output); } mjob.Settings.DAR = video.DAR; } else if (o.outputType is AudioType) { MuxStream stream = audioStreams.Find(delegate(MuxStream m) { return(VideoUtil.guessAudioType(m.path) == o.outputType); }); if (stream != null) { mjob.Settings.AudioStreams.Add(stream); audioStreams.Remove(stream); if (inputsToDelete.Contains(stream.path)) { filesToDeleteThisJob.Add(stream.path); } } } else if (o.outputType is SubtitleType) { MuxStream stream = subtitleStreams.Find(delegate(MuxStream m) { return(VideoUtil.guessSubtitleType(m.path) == o.outputType); }); if (stream != null) { mjob.Settings.SubtitleStreams.Add(stream); subtitleStreams.Remove(stream); if (inputsToDelete.Contains(stream.path)) { filesToDeleteThisJob.Add(stream.path); } } } else if (o.outputType is ChapterType) { if ((VideoUtil.guessChapterType(chapterFile) == o.outputType)) { mjob.Settings.ChapterFile = chapterFile; } if (inputsToDelete.Contains(chapterFile)) { filesToDeleteThisJob.Add(chapterFile); } } } foreach (MuxStream s in mjob.Settings.AudioStreams) { audioStreams.Remove(s); } foreach (MuxStream s in mjob.Settings.SubtitleStreams) { subtitleStreams.Remove(s); } mjob.FilesToDelete.AddRange(filesToDeleteThisJob); if (index == muxPath.Length - 1) { mjob.Settings.MuxedOutput = output; mjob.Settings.SplitSize = splitSize; mjob.Settings.DAR = video.DAR; mjob.ContainerType = container; } else { ContainerType cot = mpl.muxerInterface.GetContainersInCommon(muxPath[index + 1].muxerInterface)[0]; mjob.Settings.MuxedOutput = tempOutputName + cot.Extension; mjob.ContainerType = cot; } previousOutput = mjob.Settings.MuxedOutput; index++; jobs.Add(mjob); if (string.IsNullOrEmpty(mjob.Settings.VideoInput)) { mjob.Input = mjob.Settings.MuxedInput; } else { mjob.Input = mjob.Settings.VideoInput; } mjob.Output = mjob.Settings.MuxedOutput; mjob.MuxType = mpl.muxerInterface.MuxerType; } return(new SequentialChain(jobs.ToArray())); }