private void GenerateAviSynthScript(Size resizeTo) { SubtitleInfo sub = _jobInfo.SubtitleStreams.FirstOrDefault(item => item.HardSubIntoVideo); string subFile = string.Empty; bool keepOnlyForced = false; if (sub != null) { subFile = sub.TempFile; keepOnlyForced = sub.KeepOnlyForcedCaptions; } _jobInfo.AviSynthScript = AviSynthGenerator.Generate(_jobInfo.VideoStream, false, 0f, resizeTo, _jobInfo.EncodingProfile.StereoType, _jobInfo.StereoVideoStream, false, subFile, keepOnlyForced, AppSettings.Use64BitEncoders && AppSettings.UseFfmpegScaling); if (!string.IsNullOrEmpty(AviSynthGenerator.StereoConfigFile)) { _jobInfo.AviSynthStereoConfig = AviSynthGenerator.StereoConfigFile; } }
private string GenerateAviSynthFile() { int targetHeight; float sourceFPS = (float)Math.Round(_jobInfo.VideoStream.FPS, 3); float targetFPS = 0f; bool changeFPS = false; int targetWidth = _jobInfo.VideoStream.AspectRatio >= 1.4f ? 1024 : 720; if (_jobInfo.Input == InputType.InputDvd) { _jobInfo.VideoStream.Width = (int)Math.Round(_jobInfo.VideoStream.Height * _jobInfo.VideoStream.AspectRatio, 0); } if (_jobInfo.EncodingProfile.OutFormat == OutputType.OutputDvd) { if (_jobInfo.EncodingProfile.SystemType == 0) { targetHeight = 576; if (Math.Abs(sourceFPS - 25f) > 0) { changeFPS = true; } targetFPS = 25f; } else { targetHeight = 480; if (Math.Abs(sourceFPS - 29.970f) > 0 && Math.Abs(sourceFPS - 23.976f) > 0) { changeFPS = true; } targetFPS = (float)Math.Round(30000f / 1001f, 3); } } else { targetWidth = _jobInfo.EncodingProfile.TargetWidth; targetHeight = (int)Math.Floor(targetWidth / _jobInfo.VideoStream.AspectRatio); } Size resizeTo = new Size(targetWidth, targetHeight); SubtitleInfo sub = _jobInfo.SubtitleStreams.FirstOrDefault(item => item.HardSubIntoVideo); string subFile = string.Empty; bool keepOnlyForced = false; if (sub != null) { subFile = sub.TempFile; keepOnlyForced = sub.KeepOnlyForcedCaptions; } return(AviSynthGenerator.Generate(_jobInfo.VideoStream, changeFPS, targetFPS, resizeTo, StereoEncoding.None, new StereoVideoInfo(), true, subFile, keepOnlyForced, false)); }
public void DoEncode(object sender, DoWorkEventArgs e) { _bw = (BackgroundWorker)sender; string status = Processing.GetResourceString("lame_encoding_audio_status"); _bw.ReportProgress(-10, status); _bw.ReportProgress(0, status); AudioInfo item = _jobInfo.AudioStreams[_jobInfo.StreamId]; int outChannels = ((MP3Profile)_jobInfo.AudioProfile).OutputChannels; switch (outChannels) { case 0: outChannels = item.ChannelCount > 2 ? 2 : 0; break; case 1: outChannels = 1; break; } int outSampleRate = ((MP3Profile)_jobInfo.AudioProfile).SampleRate; switch (outSampleRate) { case 1: outSampleRate = 8000; break; case 2: outSampleRate = 11025; break; case 3: outSampleRate = 22050; break; case 4: outSampleRate = 44100; break; case 5: outSampleRate = 48000; break; default: outSampleRate = 0; break; } int encMode = ((MP3Profile)_jobInfo.AudioProfile).EncodingMode; int bitrate = ((MP3Profile)_jobInfo.AudioProfile).Bitrate; int quality = ((MP3Profile)_jobInfo.AudioProfile).Quality; string preset = ((MP3Profile)_jobInfo.AudioProfile).Preset; string inputFile = AviSynthGenerator.GenerateAudioScript(item.TempFile, item.Format, item.FormatProfile, item.ChannelCount, outChannels, item.SampleRate, outSampleRate); string outFile = Processing.CreateTempFile(item.TempFile, "encoded.mp3"); StringBuilder sb = new StringBuilder(); switch (encMode) { case 2: sb.AppendFormat(AppSettings.CInfo, "-V {0:0} ", quality); break; case 0: sb.AppendFormat("--preset {0:0} ", bitrate); break; case 1: sb.AppendFormat("--preset cbr {0:0} ", bitrate); break; case 3: sb.AppendFormat("--preset {0} ", preset); break; } sb.Append("- "); sb.AppendFormat(AppSettings.CInfo, "\"{0}\" ", outFile); string localExecutable = Path.Combine(AppSettings.ToolsPath, Executable); _startTime = DateTime.Now; using (Process encoder = new Process(), decoder = BePipe.GenerateProcess(inputFile)) { ProcessStartInfo encoderParameter = new ProcessStartInfo(localExecutable) { WorkingDirectory = AppSettings.DemuxLocation, Arguments = sb.ToString(), CreateNoWindow = true, UseShellExecute = false, RedirectStandardError = true, RedirectStandardInput = true }; encoder.StartInfo = encoderParameter; decoder.StartInfo.RedirectStandardError = true; decoder.ErrorDataReceived += OnDecoderOnErrorDataReceived; encoder.ErrorDataReceived += OnEncoderOnErrorDataReceived; Log.InfoFormat("lame {0:s}", encoderParameter.Arguments); bool encStarted; bool decStarted; try { encStarted = encoder.Start(); } catch (Exception ex) { encStarted = false; Log.ErrorFormat("lame exception: {0}", ex); _jobInfo.ExitCode = -1; } try { decStarted = decoder.Start(); } catch (Exception ex) { decStarted = false; Log.ErrorFormat("bepipe exception: {0}", ex); _jobInfo.ExitCode = -1; } if (encStarted && decStarted) { encoder.PriorityClass = AppSettings.GetProcessPriority(); encoder.BeginErrorReadLine(); decoder.PriorityClass = AppSettings.GetProcessPriority(); decoder.BeginErrorReadLine(); Processing.CopyStreamToStream(decoder.StandardOutput.BaseStream, encoder.StandardInput.BaseStream, 32768, (src, dst, exc) => { src.Close(); dst.Close(); if (exc == null) { return; } Log.Debug(exc.Message); Log.Debug(exc.StackTrace); }); while (!encoder.HasExited) { if (_bw.CancellationPending) { encoder.Kill(); decoder.Kill(); } Thread.Sleep(200); } encoder.WaitForExit(10000); encoder.CancelErrorRead(); decoder.WaitForExit(10000); decoder.CancelErrorRead(); _jobInfo.ExitCode = encoder.ExitCode; Log.InfoFormat("Exit Code: {0:g}", _jobInfo.ExitCode); if (_jobInfo.ExitCode == 0) { _jobInfo.TempFiles.Add(inputFile); _jobInfo.TempFiles.Add(item.TempFile); _jobInfo.TempFiles.Add(item.TempFile + ".d2a"); _jobInfo.TempFiles.Add(item.TempFile + ".ffindex"); item.TempFile = outFile; AudioHelper.GetStreamInfo(item); } } } _bw.ReportProgress(100); _jobInfo.CompletedStep = _jobInfo.NextStep; e.Result = _jobInfo; }
/// <summary> /// crop detection function, called by BackgroundWorker thread /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void GetCrop(object sender, DoWorkEventArgs e) { _bw = (BackgroundWorker)sender; _bw.ReportProgress(-10, _cropDetectStatus); _bw.ReportProgress(0); string inputFile = AviSynthGenerator.GenerateCropDetect(_jobInfo.VideoStream.TempFile, _jobInfo.VideoStream.FPS, _jobInfo.VideoStream.Length, new Size(_jobInfo.VideoStream.Width, _jobInfo.VideoStream.Height), _jobInfo.VideoStream.AspectRatio, out _cropDetectFrames); string localExecutable = Path.Combine(AppSettings.ToolsPath, Executable); using (Process encoder = new Process()) { ProcessStartInfo encoderParameter = new ProcessStartInfo(localExecutable) { WorkingDirectory = AppSettings.DemuxLocation, Arguments = string.Format(AppSettings.CInfo, " -threads {0:g} -i \"{1:s}\" -vf cropdetect -vcodec rawvideo -an -sn -f matroska -y NUL", Environment.ProcessorCount + 1, inputFile), CreateNoWindow = true, UseShellExecute = false, RedirectStandardError = true }; encoder.StartInfo = encoderParameter; encoder.ErrorDataReceived += CropDetectOnErrorDataReceived; Log.InfoFormat("ffmpeg {0:s}", encoderParameter.Arguments); bool encstarted; try { encstarted = encoder.Start(); } catch (Exception ex) { encstarted = false; Log.ErrorFormat("ffmpeg exception: {0}", ex); _jobInfo.ExitCode = -1; } if (encstarted) { encoder.PriorityClass = AppSettings.GetProcessPriority(); encoder.BeginErrorReadLine(); _bw.ReportProgress(-1, _cropDetectStatus); _jobInfo.VideoStream.CropRect = new Rectangle(); while (!encoder.HasExited) { if (_bw.CancellationPending) { encoder.Kill(); } Thread.Sleep(200); } encoder.WaitForExit(10000); encoder.CancelErrorRead(); _jobInfo.ExitCode = encoder.ExitCode; Log.InfoFormat("Exit Code: {0:g}", _jobInfo.ExitCode); } } int mod16Temp; int mod16Width = Math.DivRem(_jobInfo.VideoStream.Width, 16, out mod16Temp); mod16Width *= 16; int mod16Height = Math.DivRem(_jobInfo.VideoStream.Height, 16, out mod16Temp); mod16Height *= 16; if (_jobInfo.VideoStream.CropRect.Width == mod16Width) { _jobInfo.VideoStream.CropRect.Width = _jobInfo.VideoStream.Width; Point lPoint = _jobInfo.VideoStream.CropRect.Location; lPoint.X = 0; _jobInfo.VideoStream.CropRect.Location = lPoint; } if (_jobInfo.VideoStream.CropRect.Height == mod16Height) { _jobInfo.VideoStream.CropRect.Height = _jobInfo.VideoStream.Height; Point lPoint = _jobInfo.VideoStream.CropRect.Location; lPoint.Y = 0; _jobInfo.VideoStream.CropRect.Location = lPoint; } _bw.ReportProgress(100); _jobInfo.CompletedStep = _jobInfo.NextStep; _jobInfo.TempFiles.Add(inputFile); e.Result = _jobInfo; }
/// <summary> /// AC3 encode processing function, called by BackgroundWorker thread /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void DoEncodeAc3(object sender, DoWorkEventArgs e) { _bw = (BackgroundWorker)sender; bool use64BitEncoder = AppSettings.Use64BitEncoders && AppSettings.Ffmpeg64Installed && Environment.Is64BitOperatingSystem; int[] sampleRateArr = { 0, 8000, 11025, 22050, 44100, 48000 }; int[] channelArr = { 0, 2, 3, 4, 1 }; string status = Processing.GetResourceString("ffmpeg_encoding_audio_status"); _bw.ReportProgress(-10, status); _bw.ReportProgress(0, status); AudioInfo item = _jobInfo.AudioStreams[_jobInfo.StreamId]; int outChannels = -1; int outSampleRate = -1; switch (_jobInfo.AudioProfile.Type) { case ProfileType.AC3: outChannels = ((AC3Profile)_jobInfo.AudioProfile).OutputChannels; outChannels = channelArr[outChannels]; if (item.ChannelCount > 6) { outChannels = 6; } outSampleRate = ((AC3Profile)_jobInfo.AudioProfile).SampleRate; outSampleRate = sampleRateArr[outSampleRate]; break; case ProfileType.Copy: outChannels = item.ChannelCount > 6 ? 6 : item.ChannelCount; outSampleRate = item.SampleRate; if (_jobInfo.EncodingProfile.OutFormat == OutputType.OutputDvd && outSampleRate != 48000) { outSampleRate = 48000; } break; } string inputFile = AviSynthGenerator.GenerateAudioScript(item.TempFile, item.Format, item.FormatProfile, item.ChannelCount, outChannels, item.SampleRate, outSampleRate); string outFile = Processing.CreateTempFile(item.TempFile, "encoded.ac3"); string localExecutable = Path.Combine(AppSettings.ToolsPath, use64BitEncoder ? Executable64 : Executable); DateTime startTime = DateTime.Now; using (Process encoder = new Process(), decoder = BePipe.GenerateProcess(inputFile)) { ProcessStartInfo encoderParameter = new ProcessStartInfo(localExecutable) { WorkingDirectory = AppSettings.DemuxLocation, Arguments = FfmpegCommandLineGenerator.GenerateAC3EncodeLine( _jobInfo, "-", outFile), CreateNoWindow = true, UseShellExecute = false, RedirectStandardError = true, RedirectStandardInput = true }; encoder.StartInfo = encoderParameter; _localItem = item; _encodingStart = startTime; encoder.ErrorDataReceived += Ac3EncodeOnErrorDataReceived; Log.InfoFormat("ffmpeg {0:s}", encoderParameter.Arguments); bool encStarted; bool decStarted; try { encStarted = encoder.Start(); } catch (Exception ex) { encStarted = false; Log.ErrorFormat("ffmpeg exception: {0}", ex); _jobInfo.ExitCode = -1; } try { decStarted = decoder.Start(); } catch (Exception ex) { decStarted = false; Log.ErrorFormat("bepipe exception: {0}", ex); _jobInfo.ExitCode = -1; } if (encStarted && decStarted) { encoder.PriorityClass = AppSettings.GetProcessPriority(); encoder.BeginErrorReadLine(); decoder.PriorityClass = AppSettings.GetProcessPriority(); Processing.CopyStreamToStream(decoder.StandardOutput.BaseStream, encoder.StandardInput.BaseStream, 32768, (src, dst, exc) => { src.Close(); dst.Close(); if (exc == null) { return; } Log.Debug(exc.Message); Log.Debug(exc.StackTrace); }); while (!encoder.HasExited) { if (_bw.CancellationPending) { encoder.Kill(); decoder.Kill(); } Thread.Sleep(200); } encoder.WaitForExit(10000); encoder.CancelErrorRead(); decoder.WaitForExit(10000); _jobInfo.ExitCode = encoder.ExitCode; Log.InfoFormat("Exit Code: {0:g}", _jobInfo.ExitCode); if (_jobInfo.ExitCode == 0) { _jobInfo.TempFiles.Add(inputFile); _jobInfo.TempFiles.Add(item.TempFile); _jobInfo.TempFiles.Add(item.TempFile + ".d2a"); _jobInfo.TempFiles.Add(item.TempFile + ".ffindex"); item.TempFile = outFile; AudioHelper.GetStreamInfo(item); } } } _bw.ReportProgress(100); _jobInfo.CompletedStep = _jobInfo.NextStep; e.Result = _jobInfo; }