Пример #1
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);
 }
Пример #2
0
        public MuxPath Clone()
        {
            MuxPath nMuxPath = new MuxPath(initialInputTypes, targetType);

            nMuxPath.path.AddRange(path);
            return(nMuxPath);
        }
Пример #3
0
        /// <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));
        }
Пример #4
0
        /// <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);
        }
Пример #5
0
        /// <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));
        }
Пример #6
0
        public bool CanBeMuxed(ContainerType containerType, params MuxableType[] allTypes)
        {
            MuxPath muxPath = GetMuxPath(containerType, false, allTypes);

            if (muxPath != null)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Пример #7
0
 /// <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);
     }
 }
Пример #8
0
        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);
            }
        }
Пример #9
0
        /// <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);
        }
Пример #10
0
        /// <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));
            }
        }
Пример #11
0
        /// <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));
            }
        }
Пример #12
0
        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;
                    }
                }
            }
        }
Пример #13
0
        /// <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);
        }
Пример #14
0
        /// <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);
            }
        }
Пример #15
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));
        }
Пример #16
0
 public MuxPath Clone()
 {
     MuxPath nMuxPath = new MuxPath(initialInputTypes, targetType);
     nMuxPath.path.AddRange(path);
     return nMuxPath;
 }
Пример #17
0
        /// <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;
        }
Пример #18
0
 /// <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;
 }
Пример #19
0
 /// <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;
 }
Пример #20
0
 /// <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);
 }
Пример #21
0
 /// <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;
     }
 }
Пример #22
0
        /// <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;
            }
        }
Пример #23
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;
 }
Пример #24
0
        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()));
        }
Пример #25
0
        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()));
        }