};\r
\r
// Sanatise the input.\r
- Geometry resultGeometry = AnamorphicFactory.CreateGeometry(job, new SourceVideoInfo(null, null, new Size(title.Geometry.Width, title.Geometry.Height), new Size(title.Geometry.PAR.Num, title.Geometry.PAR.Den)), AnamorphicFactory.KeepSetting.HB_KEEP_WIDTH); // TODO this keep isn't right.\r
+ Geometry resultGeometry = AnamorphicFactory.CreateGeometry(job, new SourceVideoInfo(new Size(title.Geometry.Width, title.Geometry.Height), new Size(title.Geometry.PAR.Num, title.Geometry.PAR.Den)), AnamorphicFactory.KeepSetting.HB_KEEP_WIDTH); // TODO this keep isn't right.\r
int width = resultGeometry.Width * resultGeometry.PAR.Num / resultGeometry.PAR.Den;\r
int height = resultGeometry.Height;\r
uiGeometry.geometry.height = resultGeometry.Height; // Prased the height now.\r
/// Gets or sets the title.\r
/// </summary>\r
public int Title { get; set; }\r
+\r
+ /// <summary>\r
+ /// Gets or sets the path.\r
+ /// </summary>\r
+ public string Path { get; set; }\r
}\r
}
\ No newline at end of file
/// <summary>\r
/// Initializes a new instance of the <see cref="SourceVideoInfo"/> class.\r
/// </summary>\r
- /// <param name="framerateNumerator">\r
- /// The framerate numerator.\r
- /// </param>\r
- /// <param name="framerateDenominator">\r
- /// The framerate denominator.\r
- /// </param>\r
/// <param name="resolution">\r
/// The resolution.\r
/// </param>\r
/// <param name="parVal">\r
/// The par val.\r
/// </param>\r
- public SourceVideoInfo(int? framerateNumerator, int? framerateDenominator, Size resolution, Size parVal)\r
+ public SourceVideoInfo(Size resolution, Size parVal)\r
{\r
- this.FramerateNumerator = framerateNumerator;\r
- this.FramerateDenominator = framerateDenominator;\r
this.Resolution = resolution;\r
this.ParVal = parVal;\r
}\r
\r
- /// <summary>\r
- /// Gets the framerate numerator.\r
- /// </summary>\r
- public int? FramerateNumerator { get; private set; }\r
-\r
- /// <summary>\r
- /// Gets the framerate denominator.\r
- /// </summary>\r
- public int? FramerateDenominator { get; private set; }\r
-\r
/// <summary>\r
/// Gets or sets the resolution (width/height) of this Title\r
/// </summary>\r
}\r
}\r
\r
- /// <summary>\r
- /// Pase the status output (from standard output)\r
- /// </summary>\r
- /// <param name="encodeStatus">\r
- /// The encode Status.\r
- /// </param>\r
- /// <param name="startTime">\r
- /// The start Time.\r
- /// </param>\r
- /// <returns>\r
- /// The <see cref="EncodeProgressEventArgs"/>.\r
- /// </returns>\r
- public EncodeProgressEventArgs ReadEncodeStatus(string encodeStatus, DateTime startTime)\r
- {\r
- try\r
- {\r
- Match m = Regex.Match(\r
- encodeStatus, \r
- @"^Encoding: task ([0-9]*) of ([0-9]*), ([0-9]*\.[0-9]*) %( \(([0-9]*\.[0-9]*) fps, avg ([0-9]*\.[0-9]*) fps, ETA ([0-9]{2})h([0-9]{2})m([0-9]{2})s\))?");\r
-\r
- if (m.Success)\r
- {\r
- int currentTask = int.Parse(m.Groups[1].Value);\r
- int totalTasks = int.Parse(m.Groups[2].Value);\r
- float percent = float.Parse(m.Groups[3].Value, CultureInfo.InvariantCulture);\r
- float currentFps = m.Groups[5].Value == string.Empty\r
- ? 0.0F\r
- : float.Parse(m.Groups[5].Value, CultureInfo.InvariantCulture);\r
- float avgFps = m.Groups[6].Value == string.Empty\r
- ? 0.0F\r
- : float.Parse(m.Groups[6].Value, CultureInfo.InvariantCulture);\r
- string remaining = string.Empty;\r
- if (m.Groups[7].Value != string.Empty)\r
- {\r
- remaining = m.Groups[7].Value + ":" + m.Groups[8].Value + ":" + m.Groups[9].Value;\r
- }\r
- if (string.IsNullOrEmpty(remaining))\r
- {\r
- remaining = "Calculating ...";\r
- }\r
-\r
- EncodeProgressEventArgs eventArgs = new EncodeProgressEventArgs\r
- {\r
- AverageFrameRate = avgFps, \r
- CurrentFrameRate = currentFps, \r
- EstimatedTimeLeft =\r
- Converters.EncodeToTimespan(\r
- remaining), \r
- PercentComplete = percent, \r
- Task = currentTask, \r
- TaskCount = totalTasks, \r
- ElapsedTime =\r
- DateTime.Now - startTime, \r
- };\r
-\r
- return eventArgs;\r
- }\r
-\r
- return null;\r
- }\r
- catch (Exception)\r
- {\r
- return null;\r
- }\r
- }\r
-\r
/// <summary>\r
/// Setup the logging.\r
/// </summary>\r
using System.Runtime.InteropServices;\r
\r
using HandBrake.ApplicationServices.Interop;\r
- using HandBrake.ApplicationServices.Interop.Factories;\r
using HandBrake.ApplicationServices.Interop.HbLib;\r
using HandBrake.ApplicationServices.Interop.Helpers;\r
using HandBrake.ApplicationServices.Interop.Json.Anamorphic;\r
using HandBrake.ApplicationServices.Interop.Json.Encode;\r
- using HandBrake.ApplicationServices.Interop.Model;\r
using HandBrake.ApplicationServices.Interop.Model.Encoding;\r
using HandBrake.ApplicationServices.Model;\r
using HandBrake.ApplicationServices.Services.Encode.Model;\r
/// <param name="job">\r
/// The encode job.\r
/// </param>\r
- /// <param name="title">\r
- /// The title.\r
- /// </param>\r
/// <param name="configuration">\r
/// The configuration.\r
/// </param>\r
/// <returns>\r
/// The <see cref="JsonEncodeObject"/>.\r
/// </returns>\r
- internal static JsonEncodeObject Create(EncodeTask job, SourceVideoInfo title, HBConfiguration configuration)\r
+ internal static JsonEncodeObject Create(EncodeTask job, HBConfiguration configuration) \r
{\r
JsonEncodeObject encode = new JsonEncodeObject\r
{\r
SequenceID = 0, \r
Audio = CreateAudio(job), \r
Destination = CreateDestination(job), \r
- Filter = CreateFilter(job, title), \r
- PAR = CreatePAR(job, title), \r
+ Filter = CreateFilter(job), \r
+ PAR = CreatePAR(job), \r
MetaData = CreateMetaData(job),\r
Source = CreateSource(job, configuration), \r
Subtitle = CreateSubtitle(job), \r
{\r
Title = job.Title, \r
Range = range,\r
- Angle = job.Angle\r
+ Angle = job.Angle,\r
+ Path = job.Source,\r
};\r
return source;\r
}\r
/// <param name="job">\r
/// The Job\r
/// </param>\r
- /// <param name="title">\r
- /// The title.\r
- /// </param>\r
/// <returns>\r
/// The produced PAR object.\r
/// </returns>\r
- private static PAR CreatePAR(EncodeTask job, SourceVideoInfo title)\r
+ private static PAR CreatePAR(EncodeTask job)\r
{\r
- Geometry resultGeometry = AnamorphicFactory.CreateGeometry(job, title, AnamorphicFactory.KeepSetting.HB_KEEP_WIDTH);\r
- return new PAR { Num = resultGeometry.PAR.Num, Den = resultGeometry.PAR.Den };\r
+ return new PAR { Num = job.PixelAspectX, Den = job.PixelAspectY };\r
}\r
\r
/// <summary>\r
/// <param name="job">\r
/// The job.\r
/// </param>\r
- /// <param name="title">\r
- /// The title.\r
- /// </param>\r
/// <returns>\r
/// The <see cref="Filter"/>.\r
/// </returns>\r
- private static Filter CreateFilter(EncodeTask job, SourceVideoInfo title)\r
+ private static Filter CreateFilter(EncodeTask job)\r
{\r
Filter filter = new Filter\r
{\r
IntPtr frameratePrt = Marshal.StringToHGlobalAnsi(job.Framerate.ToString()); // TODO check culture\r
int vrate = HBFunctions.hb_video_framerate_get_from_name(frameratePrt);\r
\r
- int num;\r
- int den;\r
+ int? num = null;\r
+ int? den = null;\r
if (vrate > 0)\r
{\r
num = 27000000;\r
den = vrate;\r
}\r
- else\r
- {\r
- // cfr or pfr flag with no rate specified implies use the title rate.\r
- num = title.FramerateNumerator ?? 0;\r
- den = title.FramerateDenominator ?? 0;\r
- }\r
\r
- string framerateString = string.Format("{0}:{1}:{2}", fm, num, den); // filter_cfr, filter_vrate.num, filter_vrate.den\r
+ string framerateString = num.HasValue ? string.Format("{0}:{1}:{2}", fm, num, den) : string.Format("{0}", fm); // filter_cfr, filter_vrate.num, filter_vrate.den\r
\r
FilterList framerateShaper = new FilterList { ID = (int)hb_filter_ids.HB_FILTER_VFR, Settings = framerateString };\r
filter.FilterList.Add(framerateShaper);\r
}\r
\r
// CropScale Filter\r
- Geometry resultGeometry = AnamorphicFactory.CreateGeometry(job, title, AnamorphicFactory.KeepSetting.HB_KEEP_WIDTH);\r
FilterList cropScale = new FilterList\r
{\r
ID = (int)hb_filter_ids.HB_FILTER_CROP_SCALE, \r
Settings =\r
string.Format(\r
"{0}:{1}:{2}:{3}:{4}:{5}", \r
- resultGeometry.Width, \r
- resultGeometry.Height, \r
+ job.Width, \r
+ job.Height, \r
job.Cropping.Top, \r
job.Cropping.Bottom, \r
job.Cropping.Left, \r
/// </summary>\r
int LogIndex { get; }\r
\r
- /// <summary>\r
- /// Gets a value indicating whether can pause.\r
- /// </summary>\r
- bool CanPause { get; }\r
-\r
/// <summary>\r
/// Gets a value indicating whether is pasued.\r
/// </summary>\r
{\r
using System;\r
using System.Diagnostics;\r
- using System.Linq;\r
- using System.ServiceModel.Channels;\r
\r
- using HandBrake.ApplicationServices.Model;\r
- using HandBrake.ApplicationServices.Services.Encode.Interfaces;\r
- using HandBrake.ApplicationServices.Services.Scan;\r
- using HandBrake.ApplicationServices.Services.Scan.Model;\r
- using HandBrake.ApplicationServices.Utilities;\r
using HandBrake.ApplicationServices.Interop;\r
using HandBrake.ApplicationServices.Interop.EventArgs;\r
using HandBrake.ApplicationServices.Interop.Interfaces;\r
using HandBrake.ApplicationServices.Interop.Model;\r
+ using HandBrake.ApplicationServices.Model;\r
using HandBrake.ApplicationServices.Services.Encode.Factories;\r
+ using HandBrake.ApplicationServices.Services.Encode.Interfaces;\r
\r
/// <summary>\r
/// LibHB Implementation of IEncode\r
/// </summary>\r
private QueueTask currentTask;\r
\r
- /// <summary>\r
- /// A local instance of the scanned source.\r
- /// </summary>\r
- private Source scannedSource;\r
-\r
#endregion\r
\r
- /// <summary>\r
- /// Initializes a new instance of the <see cref="LibEncode"/> class.\r
- /// </summary>\r
- public LibEncode()\r
- {\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
/// Gets a value indicating whether is pasued.\r
/// </summary>\r
/// </param>\r
public void Start(QueueTask job)\r
{\r
- // Setup\r
- this.startTime = DateTime.Now;\r
- this.currentTask = job;\r
-\r
- // Create a new HandBrake instance\r
- // Setup the HandBrake Instance\r
- HandBrakeUtils.MessageLogged += this.HandBrakeInstanceMessageLogged;\r
- HandBrakeUtils.ErrorLogged += this.HandBrakeInstanceErrorLogged;\r
- this.instance = HandBrakeInstanceManager.GetEncodeInstance(job.Configuration.Verbosity);\r
- this.instance.EncodeCompleted += this.InstanceEncodeCompleted;\r
- this.instance.EncodeProgress += this.InstanceEncodeProgress;\r
- \r
try\r
{\r
+ // Setup\r
+ this.startTime = DateTime.Now;\r
+ this.currentTask = job;\r
+\r
+ // Create a new HandBrake instance\r
+ // Setup the HandBrake Instance\r
+ HandBrakeUtils.MessageLogged += this.HandBrakeInstanceMessageLogged;\r
+ HandBrakeUtils.ErrorLogged += this.HandBrakeInstanceErrorLogged;\r
+ this.instance = HandBrakeInstanceManager.GetEncodeInstance(job.Configuration.Verbosity);\r
+ this.instance.EncodeCompleted += this.InstanceEncodeCompleted;\r
+ this.instance.EncodeProgress += this.InstanceEncodeProgress;\r
+\r
// Sanity Checking and Setup\r
if (this.IsEncoding)\r
{\r
throw new Exception("HandBrake is already encoding.");\r
}\r
-\r
+ \r
this.IsEncoding = true;\r
-\r
- // Enable logging if required.\r
- try\r
- {\r
- this.SetupLogging(job, true);\r
- }\r
- catch (Exception)\r
- {\r
- this.IsEncoding = false;\r
- throw;\r
- }\r
+ this.SetupLogging(job, true);\r
\r
// Verify the Destination Path Exists, and if not, create it.\r
this.VerifyEncodeDestinationPath(job);\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
-\r
- this.instance.ScanCompleted += delegate\r
- {\r
- // Process into internal structures.\r
- this.scannedSource = new Source { Titles = LibScan.ConvertTitles(this.instance.Titles) }; // TODO work around the bad Internal API.\r
- this.ScanCompleted(job, this.instance);\r
- };\r
+ ServiceLogMessage("Starting Encode ...");\r
\r
- HandBrakeUtils.SetDvdNav(!job.Configuration.IsDvdNavDisabled);\r
+ // Get an EncodeJob object for the Interop Library\r
+ instance.StartEncode(EncodeFactory.Create(job.Task, job.Configuration));\r
\r
- ServiceLogMessage("Scanning title for encoding ... ");\r
+ // Fire the Encode Started Event\r
+ this.InvokeEncodeStarted(System.EventArgs.Empty);\r
\r
- this.instance.StartScan(job.ScannedSourcePath, job.Configuration.PreviewScanCount, TimeSpan.FromSeconds(job.Configuration.MinScanDuration), job.Task.Title);\r
+ // Set the Process Priority\r
+ switch (job.Configuration.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
catch (Exception exc)\r
{\r
- ServiceLogMessage("Scan Failed ... " + Environment.NewLine + exc);\r
- this.InvokeEncodeCompleted(new EventArgs.EncodeCompletedEventArgs(false, exc, "An Error has occured.", this.currentTask.Task.Destination));\r
+ this.IsEncoding = false;\r
+\r
+ ServiceLogMessage("Failed to start encoding ..." + Environment.NewLine + exc);\r
+ this.InvokeEncodeCompleted(new EventArgs.EncodeCompletedEventArgs(false, exc, "Unable to start encoding", job.Task.Source));\r
}\r
}\r
\r
}\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
- try\r
- {\r
- ServiceLogMessage("Scan Completed. Setting up the job for encoding ...");\r
-\r
- // Start the Encode\r
- Title title = this.scannedSource.Titles.FirstOrDefault(t => t.TitleNumber == job.Task.Title);\r
- if (title == null)\r
- {\r
- ServiceLogMessage("Title not found.");\r
- throw new Exception("Unable to get title for encoding. Encode Failed.");\r
- }\r
-\r
- ServiceLogMessage("Starting Encode ...");\r
-\r
- // Get an EncodeJob object for the Interop Library\r
- SourceVideoInfo videoInfo = new SourceVideoInfo(title.FramerateNumerator, title.FramerateDenominator, title.Resolution, title.ParVal);\r
- instance.StartEncode(EncodeFactory.Create(job.Task, videoInfo, job.Configuration));\r
-\r
- // Fire the Encode Started Event\r
- this.InvokeEncodeStarted(System.EventArgs.Empty);\r
-\r
- // Set the Process Priority\r
- switch (job.Configuration.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
- catch (Exception exc)\r
- {\r
- this.IsEncoding = false;\r
-\r
- ServiceLogMessage("Failed to start encoding ..." + Environment.NewLine + exc);\r
- this.InvokeEncodeCompleted(new EventArgs.EncodeCompletedEventArgs(false, exc, "Unable to start encoding", job.Task.Source));\r
- }\r
- }\r
\r
#region HandBrakeInstance Event Handlers.\r
\r
this.EncodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted;\r
this.EncodeService.EncodeCompleted += this.EncodeServiceEncodeCompleted;\r
\r
- if (this.EncodeService.CanPause && this.EncodeService.IsEncoding)\r
+ if (this.EncodeService.IsEncoding)\r
{\r
this.EncodeService.Resume();\r
}\r
set\r
{\r
this.isEncoding = value;\r
- this.CanPause = value && this.encodeService.CanPause;\r
+ this.CanPause = value;\r
this.NotifyOfPropertyChange(() => this.IsEncoding);\r
}\r
}\r
public void PauseEncode()\r
{\r
this.queueProcessor.Pause();\r
-\r
- if (this.encodeService.CanPause)\r
- {\r
- this.encodeService.Pause();\r
- this.IsEncoding = false;\r
- }\r
+ this.encodeService.Pause();\r
+ this.IsEncoding = false;\r
}\r
\r
/// <summary>\r
\r
// Step 2, For the changed field, call hb_set_anamorphic_size and process the results.\r
PictureSize.AnamorphicResult result = PictureSize.hb_set_anamorphic_size2(this.GetPictureSettings(), this.GetPictureTitleInfo(), setting);\r
-\r
- switch (this.SelectedAnamorphicMode)\r
- {\r
- case Anamorphic.None:\r
- this.Task.Width = result.OutputWidth;\r
- this.Task.Height = result.OutputHeight;\r
- break;\r
- case Anamorphic.Strict:\r
- this.Task.Width = 0;\r
- this.Task.Height = 0;\r
- break;\r
- case Anamorphic.Loose:\r
- this.Task.Width = result.OutputWidth;\r
- this.Task.Height = 0;\r
- break;\r
- case Anamorphic.Custom:\r
- this.Task.Width = result.OutputWidth;\r
- this.Task.Height = result.OutputHeight;\r
- break;\r
- }\r
+ this.Task.Width = result.OutputWidth;\r
+ this.Task.Height = result.OutputHeight;\r
+ this.Task.PixelAspectX = (int)Math.Round(result.OutputParWidth, 0);\r
+ this.Task.PixelAspectY = (int)Math.Round(result.OutputParHeight, 0);\r
\r
// Step 3, Set the display width label to indicate the output.\r
double dispWidth = Math.Round((result.OutputWidth * result.OutputParWidth / result.OutputParHeight), 0);\r