public MuxPath(ContainerType targetType) { path = new List<MuxPathLeg>(); initialInputTypes = new List<MuxableType>(); this.targetType = targetType; alwaysMux = false; }
public MuxJob() : base() { codec = ""; nbOfBframes = 0; bitrate = 0; overhead = 4.3; type = MuxerType.MP4BOX; containerType = ContainerType.MP4; settings = new MuxSettings(); }
public DGIndexPostprocessingProperties() { autoDeriveAR = false; signalAR = false; autoCrop = true; keepInputResolution = false; ar = null; avsSettings = new AviSynthSettings(); horizontalOutputResolution = 640; customAR = 1.0; container = MeGUI.ContainerType.MKV; outputSize = null; splitSize = null; prerenderJob = false; deviceType = null; useChapterMarks = false; }
public JobChain GenerateJobSeries(VideoStream video, string muxedOutput, AudioJob[] audioStreams, MuxStream[] subtitles, string chapters, FileSize?desiredSize, FileSize?splitSize, ContainerType container, bool prerender, MuxStream[] muxOnlyAudio, LogItem log) { if (desiredSize.HasValue) { if (video.Settings.EncodingMode != 4 && video.Settings.EncodingMode != 8) // no automated 2/3 pass { if (this.mainForm.Settings.NbPasses == 2) { video.Settings.EncodingMode = 4; // automated 2 pass } else if (video.Settings.MaxNumberOfPasses == 3) { video.Settings.EncodingMode = 8; } } } fixFileNameExtensions(video, audioStreams, container); string videoOutput = video.Output; log.Add(eliminatedDuplicateFilenames(ref videoOutput, ref muxedOutput, audioStreams)); video.Output = videoOutput; JobChain vjobs = jobUtil.prepareVideoJob(video.Input, video.Output, video.Settings, video.DAR, prerender, true, null); if (vjobs == null) { return(null); } /* Here, we guess the types of the files based on extension. * This is guaranteed to work with MeGUI-encoded files, because * the extension will always be recognised. For non-MeGUI files, * we can only ever hope.*/ List <MuxStream> allAudioToMux = new List <MuxStream>(); List <MuxableType> allInputAudioTypes = new List <MuxableType>(); foreach (MuxStream muxStream in muxOnlyAudio) { if (VideoUtil.guessAudioMuxableType(muxStream.path, true) != null) { allInputAudioTypes.Add(VideoUtil.guessAudioMuxableType(muxStream.path, true)); allAudioToMux.Add(muxStream); } } foreach (AudioJob stream in audioStreams) { allAudioToMux.Add(stream.ToMuxStream()); allInputAudioTypes.Add(stream.ToMuxableType()); } List <MuxableType> allInputSubtitleTypes = new List <MuxableType>(); foreach (MuxStream muxStream in subtitles) { if (VideoUtil.guessSubtitleType(muxStream.path) != null) { allInputSubtitleTypes.Add(new MuxableType(VideoUtil.guessSubtitleType(muxStream.path), null)); } } MuxableType chapterInputType = null; if (!String.IsNullOrEmpty(chapters)) { ChapterType type = VideoUtil.guessChapterType(chapters); if (type != null) { chapterInputType = new MuxableType(type, null); } } List <string> inputsToDelete = new List <string>(); inputsToDelete.Add(video.Output); inputsToDelete.AddRange(Array.ConvertAll <AudioJob, string>(audioStreams, delegate(AudioJob a) { return(a.Output); })); JobChain muxJobs = this.jobUtil.GenerateMuxJobs(video, video.Framerate, allAudioToMux.ToArray(), allInputAudioTypes.ToArray(), subtitles, allInputSubtitleTypes.ToArray(), chapters, chapterInputType, container, muxedOutput, splitSize, inputsToDelete); if (desiredSize.HasValue) { BitrateCalculationInfo b = new BitrateCalculationInfo(); List <string> audiofiles = new List <string>(); foreach (MuxStream s in allAudioToMux) { audiofiles.Add(s.path); } b.AudioFiles = audiofiles; b.Container = container; b.VideoJobs = new List <TaggedJob>(vjobs.Jobs); b.DesiredSize = desiredSize.Value; ((VideoJob)vjobs.Jobs[0].Job).BitrateCalculationInfo = b; } return (new SequentialChain( new ParallelChain((Job[])audioStreams), new SequentialChain(vjobs), new SequentialChain(muxJobs))); }
/// <summary> /// sets the GUI to a minimal mode allowing to configure audio track languages, configure subtitles, and chapters /// the rest of the options are deactivated /// </summary> /// <param name="videoInput">the video input</param> /// <param name="framerate">the framerate of the video input</param> /// <param name="audioStreams">the audio streams whose languages have to be assigned</param> /// <param name="output">the output file</param> /// <param name="splitSize">the output split size</param> public void setMinimizedMode(string videoInput, VideoEncoderType videoType, double framerate, MuxStream[] audioStreams, AudioEncoderType[] audioTypes, string output, FileSize? splitSize, ContainerType cft) { base.setConfig(videoInput, (decimal)framerate, audioStreams, new MuxStream[0], null, output, splitSize, null, null); minimizedMode = true; knownVideoType = videoType; knownAudioTypes = audioTypes; // disable everything videoGroupbox.Enabled = false; for (int i = 0; i < audioStreams.Length; ++i) audioTracks[i].Enabled = false; this.output.Filename = output; this.splitting.Value = splitSize; this.muxButton.Text = "Go"; updatePossibleContainers(); if (this.cbContainer.Items.Contains(cft)) cbContainer.SelectedItem = cft; checkIO(); }
public AudioType(string name, string filterName, string extension, ContainerType containerType, AudioCodec supportedCodec) : this(name, filterName, extension, containerType, new AudioCodec[] { supportedCodec }) { }
public SubtitleType(string name, string filterName, string extension, ContainerType containerType) : base(name, filterName, extension, containerType) { }
public VideoType(string name, string filterName, string extension, ContainerType containerType, VideoCodec supportedCodec) : this(name, filterName, extension, containerType, new VideoCodec[] { supportedCodec }) { }
public MuxPath(IEnumerable <MuxableType> initialInputTypes, ContainerType targetType) : this(targetType) { this.initialInputTypes.AddRange(initialInputTypes); }
public MediaFile(List <MediaTrack> tracks, Chapters chapters, TimeSpan playTime, ContainerType container) { this.Container = container; AudioTracks = new List <AudioTrack>(); SubtitleTracks = new List <SubtitleTrack>(); foreach (MediaTrack m in tracks) { if (m is VideoTrack) { Debug.Assert(VideoTrack == null, "Only one video track per file supported"); VideoTrack = (VideoTrack)m; } if (m is AudioTrack) { AudioTracks.Add((AudioTrack)m); } if (m is SubtitleTrack) { SubtitleTracks.Add((SubtitleTrack)m); } } tracks.Sort( delegate(MediaTrack a, MediaTrack b) { return((int)a.TrackNumber - (int)b.TrackNumber); }); Tracks = tracks; Chapters = chapters; PlayTime = playTime; }
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) { 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); if (deviceOutputType != null) allTypes.Add(deviceOutputType); MuxPath muxPath = prov.GetMuxPath(container, splitSize.HasValue, 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(); 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); mjob.Settings.VideoName = video.Settings.VideoName; 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()); }
/// <summary> /// handles the selection of the output format /// in case of avi, if an encodeable audio stream is already present, /// the selection of additional streams needs to be completely disabled /// if not, it an be left enabled bt the text has to indicate the fact /// that you can only add an audio track and nothing else /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void outputFormat_CheckedChanged(object sender, System.EventArgs e) { ContainerType cot = this.container.SelectedItem as ContainerType; this.muxedOutput.Text = Path.ChangeExtension(this.muxedOutput.Text, cot.Extension); }
private void updateDeviceTypes() { if (cbContainer.SelectedItem is ContainerType && lastSelectedContainerType == cbContainer.SelectedItem as ContainerType) { return; } if (cbContainer.SelectedItem is ContainerType) { lastSelectedContainerType = cbContainer.SelectedItem as ContainerType; output.Filter = (cbContainer.SelectedItem as ContainerType).OutputFilterString; } else { output.Filter = ""; } output.Filename = Path.ChangeExtension(output.Filename, (this.cbContainer.SelectedItem as ContainerType).Extension); foreach (MuxStreamControl oStream in subtitleTracks) { if ((this.cbContainer.SelectedItem as ContainerType).Extension.Equals("mkv")) { oStream.ShowDefaultSubtitleStream = oStream.ShowForceSubtitleStream = oStream.ShowDelay = true; } else { oStream.ShowDefaultSubtitleStream = oStream.ShowForceSubtitleStream = oStream.ShowDelay = false; } } if (this.cbContainer.Text == "MKV") { this.cbType.Enabled = false; subtitleTracks[0].chkDefaultStream.Checked = true; } else { this.cbType.Enabled = true; } List <DeviceType> supportedOutputDeviceTypes = this.muxProvider.GetSupportedDevices((ContainerType)cbContainer.SelectedItem); this.cbType.Items.Clear(); this.cbType.Items.Add("Standard"); this.cbType.Items.AddRange(supportedOutputDeviceTypes.ToArray()); if (cbContainer.SelectedItem.ToString().Equals(mainForm.Settings.AedSettings.Container)) { foreach (object o in cbType.Items) // I know this is ugly, but using the DeviceOutputType doesn't work unless we're switching to manual serialization { if (o.ToString().Equals(mainForm.Settings.AedSettings.DeviceOutputType)) { cbType.SelectedItem = o; break; } } } else { this.cbType.SelectedIndex = 0; } }
/// <summary> /// handles the go button for automated encoding /// checks if we're in automated 2 pass video mode /// then the video and audio configuration is checked, and if it checks out /// the audio job, video jobs and muxing job are generated, audio and video job are linked /// and encoding is started /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void queueButton_Click(object sender, System.EventArgs e) { if (!string.IsNullOrEmpty(this.muxedOutput.Filename)) { FileSize?desiredSize = targetSize.Value; FileSize?splitSize = splitting.Value; if (FileSizeRadio.Checked) { log.LogValue("Desired Size ", desiredSize); } else if (averageBitrateRadio.Checked) { log.LogValue("Projected Bitrate ", string.Format("{0}kbps", projectedBitrateKBits.Text)); } log.LogValue("Split Size ", splitSize); MuxStream[] audio; AudioJob[] aStreams; AudioEncoderType[] muxTypes; separateEncodableAndMuxableAudioStreams(out aStreams, out audio, out muxTypes); MuxStream[] subtitles = new MuxStream[0]; string chapters = ""; string videoInput = vInfo.VideoInput; string videoOutput = vInfo.VideoOutput; string muxedOutput = this.muxedOutput.Filename; ContainerType cot = this.container.SelectedItem as ContainerType; // determine audio language foreach (MuxStream stream in audio) { foreach (KeyValuePair <string, string> strLanguage in LanguageSelectionContainer.Languages) { if (Path.GetFileNameWithoutExtension(stream.path).ToLower(System.Globalization.CultureInfo.InvariantCulture).Contains(strLanguage.Key.ToLower(System.Globalization.CultureInfo.InvariantCulture))) { stream.language = strLanguage.Key; break; } } } if (addSubsNChapters.Checked) { AdaptiveMuxWindow amw = new AdaptiveMuxWindow(mainForm); amw.setMinimizedMode(videoOutput, "", videoStream.Settings.EncoderType, jobUtil.getFramerate(videoInput), audio, muxTypes, muxedOutput, splitSize, cot); if (amw.ShowDialog() == DialogResult.OK) { amw.getAdditionalStreams(out audio, out subtitles, out chapters, out muxedOutput, out cot); } else // user aborted, abort the whole process { return; } } removeStreamsToBeEncoded(ref audio, aStreams); mainForm.Jobs.addJobsWithDependencies(vUtil.GenerateJobSeries(this.videoStream, muxedOutput, aStreams, subtitles, chapters, desiredSize, splitSize, cot, this.prerender, audio, log, this.device.Text, vInfo.Zones, null, null)); this.Close(); } }
public OutputType(string name, string filterName, string extension, ContainerType containerType) : base(name, filterName, extension) { this.containerType = containerType; }
private void setConfig(string videoInput, string muxedInput, double framerate, SubStream[] audioStreams, SubStream[] subtitleStreams, string chapterFile, string output, int splitSize, int parX, int parY, ContainerType cot) { base.setConfig(videoInput, framerate, audioStreams, subtitleStreams, chapterFile, output, splitSize, parX, parY); this.muxedInput.Text = muxedInput; this.cot = cot; this.checkIO(); }
public void getAdditionalStreams(out SubStream[] audio, out SubStream[] subtitles, out string chapters, out string output, out ContainerType cot) { cot = (containerFormat.SelectedItem as ContainerType); output = muxedOutput.Text; base.getAdditionalStreams(out audio, out subtitles, out chapters); }
public OutputType(string name, string filterName, string extension, ContainerType containerType) : base(name, filterName, extension) { this.containerType = containerType; }
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, bool deleteInputs) { 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 (deleteInputs) { 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 (deleteInputs) { 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 (deleteInputs) { filesToDeleteThisJob.Add(stream.path); } } } else if (o.outputType is ChapterType) { if ((VideoUtil.guessChapterType(chapterFile) == o.outputType)) { mjob.Settings.ChapterFile = chapterFile; } if (deleteInputs) { 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())); }
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; } } } }
public static JobChain GenerateMuxJobs(VideoStream video, decimal?framerate, MuxStream[] audioStreamsArray, MuxableType[] audioTypes, MuxStream[] subtitleStreamsArray, MuxableType[] subTypes, List <string> attachments, ChapterInfo chapterInfo, MuxableType chapterInputType, ContainerType container, string output, string timeStampFile, FileSize?splitSize, List <string> inputsToDelete, string deviceType, MuxableType deviceOutputType, bool alwaysMuxOutput) { Debug.Assert(splitSize == null || splitSize.Value != FileSize.Empty); MuxProvider prov = MainForm.Instance.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; if (framerate != null) { 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) { mjob.Settings.ChapterInfo = chapterInfo; } 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++; mjob.Settings.Attachments = attachments; mjob.Settings.TimeStampFile = timeStampFile; 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 MuxPath(IEnumerable<MuxableType> initialInputTypes, ContainerType targetType) : this(targetType) { this.initialInputTypes.AddRange(initialInputTypes); }
public SubtitleType(string name, string filterName, string extension, ContainerType containerType) : base(name, filterName, extension, containerType) { }
public MuxPath(IEnumerable<MuxableType> initialInputTypes, ContainerType targetType, bool alwaysMux) : this(initialInputTypes, targetType) { this.alwaysMux = alwaysMux; }
public VideoType(string name, string filterName, string extension, ContainerType containerType, VideoCodec[] supportedCodecs) : base(name, filterName, extension, containerType) { this.supportedCodecs = supportedCodecs; }
public static JobChain GenerateJobSeries(VideoStream video, string muxedOutput, AudioJob[] audioStreams, MuxStream[] subtitles, List <string> attachments, string timeStampFile, ChapterInfo chapterInfo, FileSize?desiredSize, FileSize?splitSize, ContainerType container, bool prerender, MuxStream[] muxOnlyAudio, LogItem log, string deviceType, Zone[] zones, string videoFileToMux, OneClickAudioTrack[] audioTracks, bool alwaysMuxOutput) { if (desiredSize.HasValue && String.IsNullOrEmpty(videoFileToMux)) { if (video.Settings.VideoEncodingType != VideoCodecSettings.VideoEncodingMode.twopassAutomated && video.Settings.VideoEncodingType != VideoCodecSettings.VideoEncodingMode.threepassAutomated) // no automated 2/3 pass { if (MainForm.Instance.Settings.NbPasses == 2) { video.Settings.VideoEncodingType = VideoCodecSettings.VideoEncodingMode.twopassAutomated; // automated 2 pass } else if (video.Settings.MaxNumberOfPasses == 3) { video.Settings.VideoEncodingType = VideoCodecSettings.VideoEncodingMode.threepassAutomated; } } } fixFileNameExtensions(video, audioStreams, container); string videoOutput = video.Output; log.Add(eliminatedDuplicateFilenames(ref videoOutput, ref muxedOutput, audioStreams)); JobChain vjobs = null; if (!String.IsNullOrEmpty(videoFileToMux)) { video.Output = videoFileToMux; } else { video.Output = videoOutput; vjobs = JobUtil.prepareVideoJob(video.Input, video.Output, video.Settings, video.DAR, prerender, zones); if (vjobs == null) { return(null); } } /* Here, we guess the types of the files based on extension. * This is guaranteed to work with MeGUI-encoded files, because * the extension will always be recognised. For non-MeGUI files, * we can only ever hope.*/ List <MuxStream> allAudioToMux = new List <MuxStream>(); List <MuxableType> allInputAudioTypes = new List <MuxableType>(); if (audioTracks != null) { // OneClick mode foreach (OneClickAudioTrack ocAudioTrack in audioTracks) { if (ocAudioTrack.DirectMuxAudio != null) { if (VideoUtil.guessAudioMuxableType(ocAudioTrack.DirectMuxAudio.path, true) != null) { allInputAudioTypes.Add(VideoUtil.guessAudioMuxableType(ocAudioTrack.DirectMuxAudio.path, true)); allAudioToMux.Add(ocAudioTrack.DirectMuxAudio); } } if (ocAudioTrack.AudioJob != null && !String.IsNullOrEmpty(ocAudioTrack.AudioJob.Input)) { allAudioToMux.Add(ocAudioTrack.AudioJob.ToMuxStream()); allInputAudioTypes.Add(ocAudioTrack.AudioJob.ToMuxableType()); } } } else { // AutoEncode mode foreach (AudioJob stream in audioStreams) { allAudioToMux.Add(stream.ToMuxStream()); allInputAudioTypes.Add(stream.ToMuxableType()); } foreach (MuxStream muxStream in muxOnlyAudio) { if (VideoUtil.guessAudioMuxableType(muxStream.path, true) != null) { allInputAudioTypes.Add(VideoUtil.guessAudioMuxableType(muxStream.path, true)); allAudioToMux.Add(muxStream); } } } List <MuxableType> allInputSubtitleTypes = new List <MuxableType>(); foreach (MuxStream muxStream in subtitles) { if (VideoUtil.guessSubtitleType(muxStream.path) != null) { allInputSubtitleTypes.Add(new MuxableType(VideoUtil.guessSubtitleType(muxStream.path), null)); } } MuxableType chapterInputType = null; if (chapterInfo.HasChapters) { chapterInputType = new MuxableType(ChapterType.OGG_TXT, null); } MuxableType deviceOutputType = null; if (!String.IsNullOrEmpty(deviceType)) { DeviceType type = VideoUtil.guessDeviceType(deviceType); if (type != null) { deviceOutputType = new MuxableType(type, null); } } List <string> inputsToDelete = new List <string>(); if (String.IsNullOrEmpty(videoFileToMux)) { inputsToDelete.Add(video.Output); } inputsToDelete.AddRange(Array.ConvertAll <AudioJob, string>(audioStreams, delegate(AudioJob a) { return(a.Output); })); JobChain muxJobs = JobUtil.GenerateMuxJobs(video, null, allAudioToMux.ToArray(), allInputAudioTypes.ToArray(), subtitles, allInputSubtitleTypes.ToArray(), attachments, chapterInfo, chapterInputType, container, muxedOutput, timeStampFile, splitSize, inputsToDelete, deviceType, deviceOutputType, alwaysMuxOutput); if (desiredSize.HasValue && String.IsNullOrEmpty(videoFileToMux)) { BitrateCalculationInfo b = new BitrateCalculationInfo(); List <string> audiofiles = new List <string>(); foreach (MuxStream s in allAudioToMux) { audiofiles.Add(s.path); } b.AudioFiles = audiofiles; b.Container = container; b.VideoJobs = new List <TaggedJob>(vjobs.Jobs); b.DesiredSize = desiredSize.Value; ((VideoJob)vjobs.Jobs[0].Job).BitrateCalculationInfo = b; } if (!String.IsNullOrEmpty(videoFileToMux)) { return(new SequentialChain(new SequentialChain((Job[])audioStreams), new SequentialChain(muxJobs))); } else { return(new SequentialChain( new SequentialChain((Job[])audioStreams), new SequentialChain(vjobs), new SequentialChain(muxJobs))); } }
public MuxPath(IEnumerable <MuxableType> initialInputTypes, ContainerType targetType, bool alwaysMux) : this(initialInputTypes, targetType) { this.alwaysMux = alwaysMux; }
private static 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; if (video.Settings == null) { path = MainForm.Instance.MuxProvider.GetMuxPath(VideoEncoderType.X264, audioCodecs, container); } else { path = MainForm.Instance.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) { if (video.Settings.EncoderType == VideoEncoderType.XVID && (type.outputType.ContainerType == ContainerType.AVI || type.outputType.ContainerType == ContainerType.MKV)) { video.Output = Path.ChangeExtension(video.Output, ".m4v"); } else if (video.Settings.EncoderType == VideoEncoderType.X264 && type.outputType.ContainerType == ContainerType.MP4) { video.Output = Path.ChangeExtension(video.Output, ".264"); } else if (video.Settings.EncoderType == VideoEncoderType.X265 && (type.outputType.ContainerType == ContainerType.MKV || type.outputType.ContainerType == ContainerType.MP4)) { video.Output = Path.ChangeExtension(video.Output, ".hevc"); } else { 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)) { string newFileName = Path.ChangeExtension(audioStreams[i].Output, type.Extension); if (!audioStreams[i].Input.Equals(newFileName)) { audioStreams[i].Output = newFileName; } break; } } } }
public AudioType(string name, string filterName, string extension, ContainerType containerType, AudioCodec[] supportedCodecs) : base(name, filterName, extension, containerType) { this.supportedCodecs = supportedCodecs; }
public MediaInfoFile(string file) { this.file = file; MediaInfo info = new MediaInfo(file); bool hasVideo = (info.Video.Count > 0); aCodecs = new AudioCodec[info.Audio.Count]; aBitrateModes = new BitrateManagementMode[info.Audio.Count]; int i = 0; foreach (MediaInfoWrapper.AudioTrack track in info.Audio) { aCodecs[i] = getAudioCodec(track.Codec); if (track.BitRateMode == "VBR") { aBitrateModes[i] = BitrateManagementMode.VBR; } else { aBitrateModes[i] = BitrateManagementMode.CBR; } } if (info.General.Count < 1) { cType = null; } else { cType = getContainerType(info.General[0].Format, info.General[0].FormatString); } if (aCodecs.Length == 1) { aType = getAudioType(aCodecs[0], cType, file); } else { aType = null; } if (hasVideo) { MediaInfoWrapper.VideoTrack track = info.Video[0]; checked { ulong width = (ulong)easyParseInt(track.Width); ulong height = (ulong)easyParseInt(track.Height); ulong frameCount = (ulong)easyParseInt(track.FrameCount); double fps = (easyParseDouble(track.FrameRate) ?? 25.0); vCodec = getVideoCodec(track.Codec); vType = getVideoType(vCodec, cType, file); Dar dar = new Dar((decimal?)easyParseDouble(track.AspectRatio), width, height); this.info = new MediaFileInfo(hasVideo, width, height, dar, frameCount, fps, aCodecs.Length > 0); } } else { this.info = new MediaFileInfo(false, 0, 0, Dar.A1x1, 0, 0, aCodecs.Length > 0); } }
public MediaFile(List<MediaTrack> tracks, Chapters chapters, TimeSpan playTime, ContainerType container) { this.Container = container; AudioTracks = new List<AudioTrack>(); SubtitleTracks = new List<SubtitleTrack>(); foreach (MediaTrack m in tracks) { if (m is VideoTrack) { Debug.Assert(VideoTrack == null, "Only one video track per file supported"); VideoTrack = (VideoTrack)m; } if (m is AudioTrack) AudioTracks.Add((AudioTrack)m); if (m is SubtitleTrack) SubtitleTracks.Add((SubtitleTrack)m); } tracks.Sort( delegate(MediaTrack a, MediaTrack b) { return (int)a.TrackNumber - (int)b.TrackNumber; }); Tracks = tracks; Chapters = chapters; PlayTime = playTime; }
public static MediaFile Open(string file) { try { MediaInfo m = new MediaInfo(file); // tracks List <MediaTrack> tracks = new List <MediaTrack>(); foreach (MediaInfoWrapper.VideoTrack t in m.Video) { VideoTrack v = new VideoTrack(); v.Codec = v.VCodec = getVideoCodec(t.Codec); v.Info = new MeGUI.core.details.TrackInfo(t.Language, t.Title); ulong width = ulong.Parse(t.Width); ulong height = ulong.Parse(t.Height); ulong frameCount = ulong.Parse(t.FrameCount); double fps = double.Parse(t.FrameRate); decimal?ar = easyParse <decimal>(delegate { return(decimal.Parse(t.AspectRatio)); }); Dar dar = new Dar(ar, width, height); v.StreamInfo = new VideoInfo2(width, height, dar, frameCount, fps); v.TrackNumber = uint.Parse(t.ID); tracks.Add(v); } foreach (MediaInfoWrapper.AudioTrack t in m.Audio) { AudioTrack a = new AudioTrack(); a.Codec = a.ACodec = getAudioCodec(t.Codec); a.Info = new MeGUI.core.details.TrackInfo(t.Language, t.Title); a.StreamInfo = new AudioInfo(); a.TrackNumber = uint.Parse(t.ID); tracks.Add(a); } foreach (MediaInfoWrapper.TextTrack t in m.Text) { SubtitleTrack s = new SubtitleTrack(); s.Codec = s.SCodec = getSubtitleCodec(t.Codec); s.Info = new MeGUI.core.details.TrackInfo(t.Language, t.Title); s.StreamInfo = new SubtitleInfo2(); s.TrackNumber = uint.Parse(t.ID); tracks.Add(s); } if (m.General.Count != 1) { throw new Exception("Expected one general track"); } GeneralTrack g = m.General[0]; ContainerType cType = getContainerType(g.Format, g.FormatString); TimeSpan playTime = TimeSpan.Parse(g.PlayTimeString3); Chapters chapters = null; if (m.Chapters.Count == 1) { chapters = parseChapters(m.Chapters[0]); } return(new MediaFile(tracks, chapters, playTime, cType)); } catch (Exception) { return(null); } }
public void getAdditionalStreams(out MuxStream[] audio, out MuxStream[] subtitles, out string chapters, out string output, out ContainerType cot) { cot = (cbContainer.SelectedItem as ContainerType); output = this.output.Filename; base.getAdditionalStreams(out audio, out subtitles, out chapters); }
private void updatePossibleContainers() { MuxableType videoType; if (minimizedMode) { videoType = null; } else { videoType = VideoUtil.guessVideoMuxableType(vInput.Filename, true); if (videoType != null && (videoType.codec == null || videoType.outputType == null)) { MessageBox.Show("Unable to determine type of input video. Mux-path finding cannot continue. Your video could well be corrupt.", "Determining type failed", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } } if (!minimizedMode && videoType == null) { this.containerFormat.Items.Clear(); this.containerFormat.Items.AddRange(muxProvider.GetSupportedContainers().ToArray()); this.containerFormat.SelectedIndex = 0; return; } MuxableType[] audioTypes; MuxableType[] subTypes; AudioEncoderType[] audioCodecs; getTypes(out audioCodecs, out audioTypes, out subTypes); List <MuxableType> allTypes = new List <MuxableType>(); if (videoType != null) { allTypes.Add(videoType); } allTypes.AddRange(audioTypes); allTypes.AddRange(subTypes); List <ContainerType> supportedOutputTypes; if (minimizedMode) { supportedOutputTypes = this.muxProvider.GetSupportedContainers(knownVideoType, audioCodecs, allTypes.ToArray()); } else { supportedOutputTypes = this.muxProvider.GetSupportedContainers(allTypes.ToArray()); } ContainerType lastSelectedFileType = null; if (containerFormat.SelectedItem is ContainerType) { lastSelectedFileType = containerFormat.SelectedItem as ContainerType; } if (supportedOutputTypes.Count > 0) { this.containerFormat.Items.Clear(); this.containerFormat.Items.AddRange(supportedOutputTypes.ToArray()); this.containerFormat.SelectedIndex = 0; if (lastSelectedFileType != null && containerFormat.Items.Contains(lastSelectedFileType)) { containerFormat.SelectedItem = lastSelectedFileType; } } else { this.containerFormat.Items.Clear(); MessageBox.Show("No muxer can be found that supports this input configuration", "Muxing impossible", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
public void getAdditionalStreams(out MuxStream[] audio, out MuxStream[] subtitles, out string chapters, out string output, out ContainerType cot) { cot = (containerFormat.SelectedItem as ContainerType); output = this.output.Filename; base.getAdditionalStreams(out audio, out subtitles, out chapters); }
private void updatePossibleContainers() { MuxableType videoType; if (minimizedMode) { videoType = knownVideoType; } else { videoType = VideoUtil.guessVideoMuxableType(videoInput.Text, true); } if (videoType == null) { this.containerFormat.Items.Clear(); this.containerFormat.Items.AddRange(muxProvider.GetSupportedContainers().ToArray()); this.containerFormat.SelectedIndex = 0; return; } MuxableType[] audioTypes; MuxableType[] subTypes; AudioEncoderType[] audioCodecs; getTypes(out audioCodecs, out audioTypes, out subTypes); List <MuxableType> allTypes = new List <MuxableType>(); allTypes.Add(videoType); allTypes.AddRange(audioTypes); allTypes.AddRange(subTypes); List <ContainerType> supportedOutputTypes; if (minimizedMode) { supportedOutputTypes = this.muxProvider.GetSupportedContainers(null, audioCodecs, allTypes.ToArray()); } else { supportedOutputTypes = this.muxProvider.GetSupportedContainers(allTypes.ToArray()); } ContainerType lastSelectedFileType = null; if (containerFormat.SelectedItem is ContainerType) { lastSelectedFileType = containerFormat.SelectedItem as ContainerType; } if (supportedOutputTypes.Count > 0) { this.containerFormat.Items.Clear(); this.containerFormat.Items.AddRange(supportedOutputTypes.ToArray()); this.containerFormat.SelectedIndex = 0; if (lastSelectedFileType != null && containerFormat.Items.Contains(lastSelectedFileType)) { containerFormat.SelectedItem = lastSelectedFileType; } } else { this.containerFormat.Items.Clear(); MessageBox.Show("No muxer can be found that supports this input configuration", "Muxing impossible", MessageBoxButtons.OK, MessageBoxIcon.Error); } }