private readonly IUserSettingService userSettingService;\r
\r
/// <summary>\r
- /// The Start time of the current Encode;\r
+ /// The instance.\r
/// </summary>\r
- private DateTime startTime;\r
+ private IHandBrakeInstance instance;\r
\r
/// <summary>\r
- /// An Instance of the HandBrake Interop Library\r
+ /// The Start time of the current Encode;\r
/// </summary>\r
- private IHandBrakeInstance instance;\r
+ private DateTime startTime;\r
\r
/// <summary>\r
/// A flag to indicate if logging is enabled or not.\r
/// <param name="userSettingService">\r
/// The user Setting Service.\r
/// </param>\r
- /// <param name="handBrakeInstance">\r
- /// The hand Brake Instance.\r
- /// </param>\r
- public LibEncode(IUserSettingService userSettingService, IHandBrakeInstance handBrakeInstance)\r
+ public LibEncode(IUserSettingService userSettingService)\r
: base(userSettingService)\r
{\r
this.userSettingService = userSettingService;\r
\r
- // Setup the HandBrake Instance\r
- this.instance = handBrakeInstance;\r
- this.instance.EncodeCompleted += this.InstanceEncodeCompleted;\r
- this.instance.EncodeProgress += this.InstanceEncodeProgress;\r
-\r
HandBrakeUtils.MessageLogged += this.HandBrakeInstanceMessageLogged;\r
HandBrakeUtils.ErrorLogged += this.HandBrakeInstanceErrorLogged;\r
}\r
\r
+ /// <summary>\r
+ /// Gets a value indicating whether can pause.\r
+ /// </summary>\r
+ public bool CanPause\r
+ {\r
+ get\r
+ {\r
+ return true;\r
+ }\r
+ }\r
+\r
/// <summary>\r
/// Start with a LibHb EncodeJob Object\r
/// </summary>\r
/// </param>\r
public void Start(QueueTask job, bool enableLogging)\r
{\r
+ // Setup\r
this.startTime = DateTime.Now;\r
this.loggingEnabled = enableLogging;\r
this.currentTask = job;\r
\r
+ // Create a new HandBrake instance\r
+ // Setup the HandBrake Instance\r
+ instance = new HandBrakeInstance();\r
+ instance.Initialize(1);\r
+ instance.EncodeCompleted += this.InstanceEncodeCompleted;\r
+ instance.EncodeProgress += this.InstanceEncodeProgress;\r
+ \r
try\r
{\r
// Sanity Checking and Setup\r
\r
this.IsEncoding = true;\r
\r
- // Get an EncodeJob object for the Interop Library\r
- EncodeJob encodeJob = InteropModelCreator.GetEncodeJob(job);\r
-\r
// Enable logging if required.\r
if (enableLogging)\r
{\r
// Verify the Destination Path Exists, and if not, create it.\r
this.VerifyEncodeDestinationPath(job);\r
\r
- // Start the Encode\r
- this.instance.StartEncode(encodeJob);\r
-\r
- // Set the Process Priority\r
- switch (this.userSettingService.GetUserSetting<string>(ASUserSettingConstants.ProcessPriority))\r
- {\r
- case "Realtime":\r
- Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime;\r
- break;\r
- case "High":\r
- Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;\r
- break;\r
- case "Above Normal":\r
- Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.AboveNormal;\r
- break;\r
- case "Normal":\r
- Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.Normal;\r
- break;\r
- case "Low":\r
- Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.Idle;\r
- break;\r
- default:\r
- Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.BelowNormal;\r
- break;\r
- }\r
+ // We have to scan the source again but only the title so the HandBrake instance is initialised correctly. \r
+ // Since the UI sends the crop params down, we don't have to do all the previews.\r
+ instance.StartScan(job.Task.Source, 1, job.Task.Title);\r
\r
- // Fire the Encode Started Event\r
- this.InvokeEncodeStarted(EventArgs.Empty);\r
+ instance.ScanCompleted += delegate\r
+ {\r
+ ScanCompleted(job, instance);\r
+ };\r
}\r
catch (Exception exc)\r
{\r
}\r
}\r
\r
+ /// <summary>\r
+ /// Pause the currently running encode.\r
+ /// </summary>\r
+ public void Pause()\r
+ {\r
+ if (this.instance != null)\r
+ {\r
+ this.instance.PauseEncode();\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Resume the currently running encode.\r
+ /// </summary>\r
+ public void Resume()\r
+ {\r
+ if (this.instance != null)\r
+ {\r
+ this.instance.ResumeEncode();\r
+ }\r
+ }\r
+\r
/// <summary>\r
/// Kill the CLI process\r
/// </summary>\r
// Nothing to do for this implementation.\r
}\r
\r
+ /// <summary>\r
+ /// The scan completed.\r
+ /// </summary>\r
+ /// <param name="job">\r
+ /// The job.\r
+ /// </param>\r
+ /// <param name="instance">\r
+ /// The instance.\r
+ /// </param>\r
+ private void ScanCompleted(QueueTask job, IHandBrakeInstance instance)\r
+ {\r
+ // Get an EncodeJob object for the Interop Library\r
+ EncodeJob encodeJob = InteropModelCreator.GetEncodeJob(job);\r
+\r
+ // Start the Encode\r
+ instance.StartEncode(encodeJob);\r
+\r
+ // Fire the Encode Started Event\r
+ this.InvokeEncodeStarted(EventArgs.Empty);\r
+\r
+ // Set the Process Priority\r
+ switch (this.userSettingService.GetUserSetting<string>(ASUserSettingConstants.ProcessPriority))\r
+ {\r
+ case "Realtime":\r
+ Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime;\r
+ break;\r
+ case "High":\r
+ Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;\r
+ break;\r
+ case "Above Normal":\r
+ Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.AboveNormal;\r
+ break;\r
+ case "Normal":\r
+ Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.Normal;\r
+ break;\r
+ case "Low":\r
+ Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.Idle;\r
+ break;\r
+ default:\r
+ Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.BelowNormal;\r
+ break;\r
+ }\r
+ }\r
+\r
#region HandBrakeInstance Event Handlers.\r
/// <summary>\r
/// Log a message\r
using HandBrake.ApplicationServices.Model.Encoding;\r
using HandBrake.Interop.Model;\r
using HandBrake.Interop.Model.Encoding;\r
+ using HandBrake.Interop.Model.Encoding.x264;\r
\r
/// <summary>\r
/// A Utility Class to Convert a \r
\r
// Which will be converted to this EncodeJob Model.\r
EncodeJob job = new EncodeJob();\r
-\r
EncodingProfile profile = new EncodingProfile();\r
job.EncodingProfile = profile;\r
\r
- profile.Anamorphic = work.Anamorphic;\r
-\r
+ // Audio Settings\r
profile.AudioEncodings = new List<AudioEncoding>();\r
job.ChosenAudioTracks = new List<int>();\r
foreach (AudioTrack track in work.AudioTracks)\r
Encoder = Converters.GetCliAudioEncoder(track.Encoder),\r
InputNumber = track.Track.HasValue ? track.Track.Value : 0,\r
Mixdown = Converters.GetCliMixDown(track.MixDown),\r
- SampleRateRaw = GetSampleRateRaw(track.SampleRate), \r
+ SampleRateRaw = GetSampleRateRaw(track.SampleRate),\r
};\r
\r
profile.AudioEncodings.Add(newTrack);\r
job.ChosenAudioTracks.Add(track.Track.Value);\r
}\r
}\r
+\r
+ // Title Settings\r
+ job.OutputPath = work.Destination;\r
+ job.SourcePath = work.Source;\r
+ job.Title = work.Title;\r
+ // job.SourceType = work.Type;\r
+ switch (work.PointToPointMode)\r
+ {\r
+ case PointToPointMode.Chapters:\r
+ job.RangeType = VideoRangeType.Chapters;\r
+ break;\r
+ case PointToPointMode.Seconds:\r
+ job.RangeType = VideoRangeType.Seconds;\r
+ break;\r
+ case PointToPointMode.Frames:\r
+ job.RangeType = VideoRangeType.Frames;\r
+ break;\r
+ }\r
+\r
+ if (work.PointToPointMode == PointToPointMode.Seconds)\r
+ {\r
+ job.SecondsEnd = work.EndPoint;\r
+ job.SecondsStart = work.StartPoint;\r
+ }\r
+ if (work.PointToPointMode == PointToPointMode.Chapters)\r
+ {\r
+ job.ChapterStart = work.StartPoint;\r
+ job.ChapterEnd = work.EndPoint;\r
+ }\r
+ if (work.PointToPointMode == PointToPointMode.Frames)\r
+ {\r
+ job.FramesEnd = work.EndPoint;\r
+ job.FramesStart = work.StartPoint;\r
+ }\r
+\r
+ job.Angle = work.Angle;\r
+ job.EncodingProfile = profile;\r
+\r
+ // Output Settings\r
+ profile.IPod5GSupport = work.IPod5GSupport;\r
+ profile.Optimize = work.OptimizeMP4;\r
+ switch (work.OutputFormat)\r
+ {\r
+ case OutputFormat.Mp4:\r
+ case OutputFormat.M4V:\r
+ profile.OutputFormat = Container.Mp4;\r
+ break;\r
+ case OutputFormat.Mkv:\r
+ profile.OutputFormat = Container.Mkv;\r
+ break;\r
+ }\r
+\r
+ // Picture Settings\r
+ profile.Anamorphic = work.Anamorphic;\r
profile.Cropping = new Cropping\r
{\r
Top = work.Cropping.Top,\r
Left = work.Cropping.Left,\r
Right = work.Cropping.Right\r
};\r
-\r
profile.CroppingType = CroppingType.Custom; // TODO deal with this better\r
+ profile.DisplayWidth = work.DisplayWidth.HasValue\r
+ ? int.Parse(Math.Round(work.DisplayWidth.Value, 0).ToString())\r
+ : 0;\r
+ profile.PixelAspectX = work.PixelAspectX;\r
+ profile.PixelAspectY = work.PixelAspectY;\r
+ profile.Height = work.Height.HasValue ? work.Height.Value : 0;\r
+ profile.KeepDisplayAspect = work.KeepDisplayAspect;\r
+ profile.MaxHeight = work.MaxHeight.HasValue ? work.MaxHeight.Value : 0;\r
+ profile.MaxWidth = work.MaxWidth.HasValue ? work.MaxWidth.Value : 0;\r
+ profile.Modulus = work.Modulus.HasValue ? work.Modulus.Value : 16;\r
+ profile.UseDisplayWidth = true;\r
+ profile.Width = work.Width.HasValue ? work.Width.Value : 0;\r
+\r
+ // Filter Settings\r
profile.CustomDecomb = work.CustomDecomb;\r
profile.CustomDeinterlace = work.CustomDeinterlace;\r
profile.CustomDenoise = work.CustomDenoise;\r
profile.CustomDetelecine = work.CustomDetelecine;\r
- profile.Deblock = work.Deblock;\r
+ if (work.Deblock > 4)\r
+ profile.Deblock = work.Deblock;\r
profile.Decomb = work.Decomb;\r
profile.Deinterlace = work.Deinterlace;\r
profile.Denoise = work.Denoise;\r
profile.Detelecine = work.Detelecine;\r
- profile.DisplayWidth = work.DisplayWidth.HasValue\r
- ? int.Parse(Math.Round(work.DisplayWidth.Value, 0).ToString())\r
- : 0;\r
- profile.Framerate = work.Framerate.HasValue ? work.Framerate.Value : 0;\r
profile.Grayscale = work.Grayscale;\r
- profile.Height = work.Height.HasValue ? work.Height.Value : 0;\r
- profile.IPod5GSupport = work.IPod5GSupport;\r
- profile.IncludeChapterMarkers = work.IncludeChapterMarkers;\r
- profile.KeepDisplayAspect = work.KeepDisplayAspect;\r
- profile.MaxHeight = work.MaxHeight.HasValue ? work.MaxHeight.Value : 0;\r
- profile.MaxWidth = work.MaxWidth.HasValue ? work.MaxWidth.Value : 0;\r
- profile.Modulus = work.Modulus.HasValue ? work.Modulus.Value : 16;\r
- profile.Optimize = work.OptimizeMP4;\r
- switch (work.OutputFormat)\r
- {\r
- case OutputFormat.Mp4:\r
- case OutputFormat.M4V:\r
- profile.OutputFormat = Container.Mp4;\r
- break;\r
- case OutputFormat.Mkv:\r
- profile.OutputFormat = Container.Mkv;\r
- break;\r
- }\r
- profile.ConstantFramerate = work.FramerateMode == FramerateMode.CFR;\r
- profile.PixelAspectX = work.PixelAspectX;\r
- profile.PixelAspectY = work.PixelAspectY;\r
\r
- switch (work.OutputFormat)\r
- {\r
- case OutputFormat.Mp4:\r
- profile.PreferredExtension = OutputExtension.Mp4;\r
- break;\r
- case OutputFormat.M4V:\r
- profile.PreferredExtension = OutputExtension.M4v;\r
- break;\r
- }\r
+ // Video Settings\r
+ profile.Framerate = work.Framerate.HasValue ? work.Framerate.Value : 0;\r
+ profile.ConstantFramerate = work.FramerateMode == FramerateMode.CFR;\r
profile.Quality = work.Quality.HasValue ? work.Quality.Value : 0;\r
- profile.UseDisplayWidth = true;\r
profile.VideoBitrate = work.VideoBitrate.HasValue ? work.VideoBitrate.Value : 0;\r
profile.VideoEncodeRateType = work.VideoEncodeRateType;\r
profile.VideoEncoder = Converters.GetVideoEncoder(work.VideoEncoder);\r
- profile.Width = work.Width.HasValue ? work.Width.Value : 0;\r
- profile.X264Options = work.AdvancedEncoderOptions;\r
\r
- if (work.PointToPointMode == PointToPointMode.Chapters)\r
+ profile.H264Level = work.H264Level;\r
+ profile.X264Profile = work.H264Profile.ToString().ToLower().Replace(" ", string.Empty); // TODO change these away from strings.\r
+ profile.X264Preset = work.X264Preset.ToString().ToLower().Replace(" ", string.Empty);\r
+ profile.X264Tunes = new List<string>();\r
+\r
+ if (work.X264Tune != x264Tune.None)\r
{\r
- job.ChapterStart = work.StartPoint;\r
- job.ChapterEnd = work.EndPoint;\r
+ profile.X264Tunes.Add(work.X264Tune.ToString().ToLower().Replace(" ", string.Empty));\r
}\r
\r
- job.Angle = work.Angle;\r
- job.EncodingProfile = profile;\r
- if (work.PointToPointMode == PointToPointMode.Frames)\r
+ if (work.FastDecode)\r
{\r
- job.FramesEnd = work.EndPoint;\r
- job.FramesStart = work.StartPoint;\r
+ profile.X264Tunes.Add("fastdecode");\r
}\r
\r
+ // Chapter Markers\r
+ profile.IncludeChapterMarkers = work.IncludeChapterMarkers;\r
job.CustomChapterNames = work.ChapterNames.Select(item => item.ChapterName).ToList();\r
job.UseDefaultChapterNames = work.IncludeChapterMarkers;\r
\r
- job.OutputPath = work.Destination;\r
- switch (work.PointToPointMode)\r
- {\r
- case PointToPointMode.Chapters:\r
- job.RangeType = VideoRangeType.Chapters;\r
- break;\r
- case PointToPointMode.Seconds:\r
- job.RangeType = VideoRangeType.Seconds;\r
- break;\r
- case PointToPointMode.Frames:\r
- job.RangeType = VideoRangeType.Frames;\r
- break;\r
- }\r
-\r
- if (work.PointToPointMode == PointToPointMode.Seconds)\r
- {\r
- job.SecondsEnd = work.EndPoint;\r
- job.SecondsStart = work.StartPoint;\r
- }\r
-\r
- job.SourcePath = work.Source;\r
- // job.SourceType = work.Type;\r
- job.Title = work.Title;\r
+ // Advanced Settings\r
+ profile.X264Options = work.AdvancedEncoderOptions;\r
\r
// Subtitles\r
job.Subtitles = new Subtitles { SourceSubtitles = new List<SourceSubtitle>(), SrtSubtitles = new List<SrtSubtitle>() };\r