A wrapper for a HandBrake instance.
상속: IHandBrakeInstance, IDisposable
예제 #1
0
        static void Main(string[] args) {
            instance = new HandBrakeInstance();
            instance.Initialize(verbosity: 1);
            instance.ScanCompleted += instance_ScanCompleted;
            instance.StartScan(SourceFile, previewCount: 10);

            Console.ReadLine();
        }
예제 #2
0
파일: LibScan.cs 프로젝트: pylam/HandBrake
        /// <summary>
        /// Initializes a new instance of the <see cref="LibScan"/> class. 
        /// </summary>
        public LibScan()
        {
            logging = new StringBuilder();

            instance = ServiceManager.HandBrakeInstance;
            instance.Initialize(1);
            instance.ScanProgress += this.InstanceScanProgress;
            instance.ScanCompleted += this.InstanceScanCompleted;

            HandBrakeUtils.MessageLogged += this.HandBrakeInstanceMessageLogged;
            HandBrakeUtils.ErrorLogged += this.HandBrakeInstanceErrorLogged;
        }
예제 #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="LibEncode"/> class.
        /// </summary>
        public LibEncode()
        {
            // Setup the HandBrake Instance
            this.instance = new HandBrakeInstance();
            this.instance.EncodeCompleted += this.InstanceEncodeCompleted;
            this.instance.EncodeProgress += this.InstanceEncodeProgress;

            HandBrakeUtils.MessageLogged += this.HandBrakeInstanceMessageLogged;
            HandBrakeUtils.ErrorLogged += this.HandBrakeInstanceErrorLogged;

            GrowlCommunicator.Register();
        }
예제 #4
0
        private void RunJob(string jobName)
        {
            this.resetEvent.Reset();

            EncodeJob job = EncodeJobsPersist.GetJob("Normal");

            if (job.SourceType == SourceType.VideoFolder)
            {
                job.SourcePath = Path.Combine(Environment.CurrentDirectory, Path.GetFileName(job.SourcePath));
            }

            if (job.SourceType == SourceType.File)
            {
                job.SourcePath = Path.Combine(Environment.CurrentDirectory, Path.GetFileName(job.SourcePath));
            }

            string extension;
            if (job.EncodingProfile.OutputFormat == OutputFormat.Mkv)
            {
                extension = ".mkv";
            }
            else
            {
                extension = ".mp4";
            }

            job.OutputPath = Path.Combine(OutputVideoDirectory, jobName + extension);

            var instance = new HandBrakeInstance();
            instance.Initialize(0);
            instance.ScanCompleted += (sender, e) =>
            {
                this.resetEvent.Set();
            };

            instance.StartScan(job.SourcePath, 10);
            this.resetEvent.WaitOne();

            this.resetEvent.Reset();
            instance.EncodeCompleted += (sender, e) =>
            {
                Assert.IsFalse(e.Error);
                this.resetEvent.Set();
            };

            instance.StartEncode(job);
            this.resetEvent.WaitOne();

            Assert.IsTrue(File.Exists(job.OutputPath));

            var fileInfo = new FileInfo(job.OutputPath);
            Assert.IsTrue(fileInfo.Length > 1024);
        }
예제 #5
0
		public void ScanNextJob()
		{
			EncodeJobViewModel jobVM = itemsToScan[currentJobIndex];

			var onDemandInstance = new HandBrakeInstance();
			onDemandInstance.Initialize(Config.LogVerbosity);
			onDemandInstance.ScanProgress += (o, e) =>
				{
					lock (this.currentJobIndexLock)
					{
						this.currentJobProgress = e.Progress;
						this.RaisePropertyChanged(() => this.Progress);
					}
				};
			onDemandInstance.ScanCompleted += (o, e) =>
				{
					jobVM.HandBrakeInstance = onDemandInstance;

					if (onDemandInstance.Titles.Count > 0)
					{
						Title titleToEncode = Utilities.GetFeatureTitle(onDemandInstance.Titles, onDemandInstance.FeatureTitle);

						jobVM.Job.Title = titleToEncode.TitleNumber;
						jobVM.Job.Length = titleToEncode.Duration;
						jobVM.Job.ChapterStart = 1;
						jobVM.Job.ChapterEnd = titleToEncode.Chapters.Count;
					}

					lock (this.currentJobIndexLock)
					{
						this.currentJobIndex++;
						this.currentJobProgress = 0;
						this.RaisePropertyChanged(() => this.Progress);

						if (this.ScanFinished)
						{
							DispatchService.BeginInvoke(() =>
							{
								this.CancelCommand.Execute(null);
							});
						}
						else
						{
							this.ScanNextJob();
						}
					}
				};

			onDemandInstance.StartScan(jobVM.Job.SourcePath, Config.PreviewCount, 0);
		}
        /// <summary>
        /// The get encode instance.
        /// </summary>
        /// <param name="verbosity">
        /// The verbosity.
        /// </param>
        /// <returns>
        /// The <see cref="IHandBrakeInstance"/>.
        /// </returns>
        public static IHandBrakeInstance GetEncodeInstance(int verbosity)
        {
            if (encodeInstance != null)
            {
                encodeInstance.Dispose();
                encodeInstance = null;
            }

            HandBrakeInstance newInstance = new HandBrakeInstance();

            newInstance.Initialize(verbosity);
            encodeInstance = newInstance;

            return(encodeInstance);
        }
        /// <summary>
        /// Gets the scanInstance.
        /// </summary>
        /// <param name="verbosity">
        /// The verbosity.
        /// </param>
        /// <returns>
        /// The <see cref="IHandBrakeInstance"/>.
        /// </returns>
        public static IHandBrakeInstance GetScanInstance(int verbosity)
        {
            if (scanInstance != null)
            {
                scanInstance.Dispose();
                scanInstance = null;
            }

            HandBrakeInstance newInstance = new HandBrakeInstance();

            newInstance.Initialize(verbosity);
            scanInstance = newInstance;

            return(scanInstance);
        }
예제 #8
0
		private void RefreshPreviews()
		{
			this.originalScanInstance = this.ScanInstance;

			this.job = this.mainViewModel.EncodeJob;
			VCProfile profile = this.job.EncodingProfile;

			int width, height, parWidth, parHeight;
			this.ScanInstance.GetSize(this.job.HbJob, out width, out height, out parWidth, out parHeight);

			// If we're rotating by 90 degrees, swap width and height for sizing purposes.
            if (profile.Rotation == VCPictureRotation.Clockwise90 || profile.Rotation == VCPictureRotation.Clockwise270)
			{
				int temp = width;
				width = height;
				height = temp;

				temp = parWidth;
				parWidth = parHeight;
				parHeight = temp;
			}

			if (parWidth <= 0 || parHeight <= 0)
			{
				this.HasPreview = false;
				this.Title = PreviewRes.NoVideoSourceTitle;

				Ioc.Container.GetInstance<ILogger>().LogError("HandBrake returned a negative pixel aspect ratio. Cannot show preview.");
				return;
			}

			this.PreviewDisplayHeight = height;
			this.PreviewDisplayWidth = width * ((double)parWidth / parHeight);

			// Update the number of previews.
			this.previewCount = this.ScanInstance.PreviewCount;
			if (this.selectedPreview >= this.previewCount)
			{
				this.selectedPreview = this.previewCount - 1;
				this.RaisePropertyChanged(() => this.SelectedPreview);
			}

			this.RaisePropertyChanged(() => this.PreviewCount);

			this.HasPreview = true;

			lock (this.imageSync)
			{
				this.previewImageCache = new BitmapSource[this.previewCount];
				updateVersion++;

				// Clear main work queue.
				this.previewImageWorkQueue.Clear();

				this.imageFileCacheFolder = Path.Combine(Utilities.ImageCacheFolder,
														 Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture),
														 updateVersion.ToString(CultureInfo.InvariantCulture));
				if (!Directory.Exists(this.imageFileCacheFolder))
				{
					Directory.CreateDirectory(this.imageFileCacheFolder);
				}

				// Clear old images out of the file cache.
				this.ClearImageFileCache();

				this.imageFileSync = new List<object>(this.previewCount);
				for (int i = 0; i < this.previewCount; i++)
				{
					this.imageFileSync.Add(new object());
				}

				this.BeginBackgroundImageLoad();
			}

			if (parWidth == parHeight)
			{
				this.Title = string.Format(PreviewRes.PreviewWindowTitleSimple, width, height);
			}
			else
			{
				this.Title = string.Format(
					PreviewRes.PreviewWindowTitleComplex,
					Math.Round(this.PreviewDisplayWidth),
					Math.Round(this.PreviewDisplayHeight),
					width,
					height);
			}
		}
예제 #9
0
		/// <summary>
		/// Starts a scan of a video source
		/// </summary>
		/// <param name="path">The path to scan.</param>
		/// <param name="jobVM">The encode job choice to apply after the scan is finished.</param>
		private void StartScan(string path, EncodeJobViewModel jobVM = null)
		{
			this.ClearVideoSource();

			this.ScanProgress = 0;
			HandBrakeInstance oldInstance = this.scanInstance;

			this.logger.Log("Starting scan: " + path);

			this.scanInstance = new HandBrakeInstance();
			this.scanInstance.Initialize(Config.LogVerbosity);
			this.scanInstance.ScanProgress += (o, e) =>
			{
				this.ScanProgress = e.Progress * 100;
			};
			this.scanInstance.ScanCompleted += (o, e) =>
			{
				DispatchService.Invoke(() =>
				{
					this.ScanningSource = false;

					if (this.scanCancelledFlag)
					{
						this.SelectedSource = null;
						this.RaisePropertyChanged(() => this.SourcePicked);

						if (this.ScanCancelled != null)
						{
							this.ScanCancelled(this, new EventArgs());
						}

						this.logger.Log("Scan cancelled");

						if (this.pendingScan != null)
						{
							this.SetSource(this.pendingScan);

							this.pendingScan = null;
						}
					}
					else
					{
						this.SourceData = new VideoSource { Titles = this.scanInstance.Titles, FeatureTitle = this.scanInstance.FeatureTitle };

						// If scan failed source data will be null.
						if (this.sourceData != null)
						{
							if (jobVM != null)
							{
								this.ApplyEncodeJobChoices(jobVM);
							}

							if (jobVM == null && this.SelectedSource != null &&
							    (this.SelectedSource.Type == SourceType.File || this.SelectedSource.Type == SourceType.VideoFolder))
							{
								SourceHistory.AddToHistory(this.SourcePath);
							}
						}

						this.logger.Log("Scan completed");
					}

					this.logger.Log("");
				});
			};

			this.ScanError = false;
			this.ScanningSource = true;
			this.scanCancelledFlag = false;
			this.scanInstance.StartScan(path, Config.PreviewCount, TimeSpan.FromSeconds(Config.MinimumTitleLengthSeconds));

			if (oldInstance != null)
			{
				this.ProcessingVM.CleanupHandBrakeInstanceIfUnused(oldInstance);
			}
		}
예제 #10
0
		// Brings up specified job for editing, doing a scan if necessary.
		public void EditJob(EncodeJobViewModel jobVM, bool isQueueItem = true)
		{
			VCJob job = jobVM.Job;

			if (this.PresetsVM.SelectedPreset.IsModified)
			{
				MessageBoxResult dialogResult = Utilities.MessageBox.Show(this, MainRes.SaveChangesPresetMessage, MainRes.SaveChangesPresetTitle, MessageBoxButton.YesNoCancel);
				if (dialogResult == MessageBoxResult.Yes)
				{
					this.PresetsVM.SavePreset();
				}
				else if (dialogResult == MessageBoxResult.No)
				{
					this.PresetsVM.RevertPreset(userInitiated: false);
				}
				else if (dialogResult == MessageBoxResult.Cancel)
				{
					return;
				}
			}

			if (jobVM.HandBrakeInstance != null && jobVM.HandBrakeInstance == this.ScanInstance)
			{
				this.ApplyEncodeJobChoices(jobVM);
				Messenger.Default.Send(new RefreshPreviewMessage());
			}
			else if (jobVM.VideoSource != null)
			{
				// Set current scan to cached scan
				this.scanInstance = jobVM.HandBrakeInstance;
				this.SourceData = jobVM.VideoSource;
				this.LoadVideoSourceMetadata(job, jobVM.VideoSourceMetadata);

				this.ApplyEncodeJobChoices(jobVM);
			}
			else
			{
				string jobPath = job.SourcePath;
				string jobRoot = Path.GetPathRoot(jobPath);

				// We need to reconstruct the source metadata since the program has shut down since the job
				// was created.
				var videoSourceMetadata = new VideoSourceMetadata();

				switch (job.SourceType)
				{
					case SourceType.Dvd:
						DriveInformation driveInfo = this.DriveCollection.FirstOrDefault(d => string.Compare(d.RootDirectory, jobRoot, StringComparison.OrdinalIgnoreCase) == 0);
						if (driveInfo == null)
						{
							Ioc.Container.GetInstance<IMessageBoxService>().Show(MainRes.DiscNotInDriveError);
							return;
						}

						videoSourceMetadata.Name = driveInfo.VolumeLabel;
						videoSourceMetadata.DriveInfo = driveInfo;
						break;
					case SourceType.File:
						videoSourceMetadata.Name = Utilities.GetSourceNameFile(job.SourcePath);
						break;
					case SourceType.VideoFolder:
						videoSourceMetadata.Name = Utilities.GetSourceNameFolder(job.SourcePath);
						break;
				}

				this.LoadVideoSourceMetadata(job, videoSourceMetadata);
				this.StartScan(job.SourcePath, jobVM);
			}

			string presetName = isQueueItem ? MainRes.PresetNameRestoredFromQueue : MainRes.PresetNameRestoredFromCompleted;

			var queuePreset = new PresetViewModel(
				new Preset
				{
					IsBuiltIn = false,
					IsModified = false,
					IsQueue = true,
					Name = presetName,
					EncodingProfile = jobVM.Job.EncodingProfile.Clone()
				});

			this.PresetsVM.InsertQueuePreset(queuePreset);

			if (isQueueItem)
			{
				// Since it's been sent back for editing, remove the queue item
				this.ProcessingVM.EncodeQueue.Remove(jobVM);
			}

			this.PresetsVM.SaveUserPresets();
		}
예제 #11
0
		/// <summary>
		/// Cleans up the given HandBrake instance if it's not being used anymore.
		/// </summary>
		/// <param name="instance">The instance to clean up.</param>
		public void CleanupHandBrakeInstanceIfUnused(HandBrakeInstance instance)
		{
			foreach (EncodeJobViewModel encodeJobVM in this.EncodeQueue)
			{
				if (instance == encodeJobVM.HandBrakeInstance)
				{
					return;
				}
			}

			foreach (EncodeResultViewModel resultVM in this.CompletedJobs)
			{
				if (instance == resultVM.Job.HandBrakeInstance)
				{
					return;
				}
			}

			if (instance == this.main.ScanInstance)
			{
				return;
			}

			instance.Dispose();
		}
예제 #12
0
		public void StartEncode(VCJob job, ILogger logger, bool preview, int previewNumber, int previewSeconds, double overallSelectedLengthSeconds)
		{
			this.logger = logger;
			this.logger.Log("Starting encode in-process");

			this.encoding = true;

			this.encodeStartEvent = new ManualResetEventSlim(false);
			this.encodeEndEvent = new ManualResetEventSlim(false);

			this.instance = new HandBrakeInstance();
			this.instance.Initialize(Config.LogVerbosity);

			this.instance.ScanCompleted += (o, e) =>
			{
				try
				{
					Title encodeTitle = this.instance.Titles.FirstOrDefault(title => title.TitleNumber == job.Title);

					if (encodeTitle != null)
					{
						lock (this.encoderLock)
						{
							this.instance.StartEncode(job.HbJob, preview, previewNumber, previewSeconds, overallSelectedLengthSeconds, Config.PreviewCount);
							this.IsEncodeStarted = true;
							if (this.EncodeStarted != null)
							{
								this.EncodeStarted(this, new EventArgs());
							}

							this.encodeStartEvent.Set();
						}
					}
					else
					{
						if (this.EncodeCompleted != null)
						{
							this.EncodeCompleted(this, new EncodeCompletedEventArgs { Error = true });
						}

						this.encodeStartEvent.Set();
						this.encodeEndEvent.Set();
					}
				}
				catch (Exception exception)
				{
					this.logger.LogError("Encoding failed. Please report this error so it can be fixed in the future:" + Environment.NewLine + exception);
				}
			};

			this.instance.EncodeProgress += (o, e) =>
			{
				// Dispatch to avoid deadlocks on callbacks
				DispatchService.BeginInvoke(() =>
				{
					lock (this.encoderLock)
					{
						if (this.encoding && this.EncodeProgress != null)
						{
							this.EncodeProgress(this, e);
						}
					}
				});
			};

			this.instance.EncodeCompleted += (o, e) =>
			{
				if (this.encoding)
				{
					if (this.EncodeCompleted != null)
					{
						this.EncodeCompleted(this, e);
					}

					this.encoding = false;
				}

				this.encodeEndEvent.Set();
				this.instance.Dispose();
			};

			this.instance.StartScan(job.SourcePath, Config.PreviewCount, job.Title);

			this.encoding = true;
		}
        /// <summary>
        /// Start the service
        /// </summary>
        /// <param name="port">
        /// The port.
        /// </param>
        public void Start(string port)
        {
            using (host = new ServiceHost(typeof(ServerService), new Uri(string.Format("net.tcp://127.0.0.1:{0}", port))))
            {
                // Setup a listener
                host.AddServiceEndpoint(typeof(IServerService), new NetTcpBinding(), "IHbService");
                host.Open();
                Console.WriteLine("::: HandBrake Isolation Server - Debug Console:::");
                Console.WriteLine("Service Started. Waiting for Clients...");

                // Setup the services we are going to use.
                IHandBrakeInstance instance = new HandBrakeInstance();
                scanService = new LibScan(instance);
                encodeService = new LibEncode(new UserSettingService(), instance); // TODO this needs wired up with castle

                shutdownFlag = new ManualResetEvent(false);
                shutdownFlag.WaitOne();
            }
        }
예제 #14
0
		public void StartEncode(EncodeJob job, bool preview, int previewNumber, int previewSeconds, double overallSelectedLengthSeconds, int verbosity, int previewCount, bool useDvdNav)
		{
			CurrentEncoder = this;
			this.callback = OperationContext.Current.GetCallbackChannel<IHandBrakeEncoderCallback>();

			try
			{
				if (this.callback == null)
				{
					throw new ArgumentException("Could not get callback channel.");
				}

				HandBrakeUtils.MessageLogged += (o, e) =>
					{
						this.StopOnException(() =>
							{
								this.callback.OnMessageLogged(e.Message);
							});
					};

				HandBrakeUtils.ErrorLogged += (o, e) =>
					{
						this.StopOnException(() =>
							{
								this.callback.OnErrorLogged(e.Message);
							});
					};

				HandBrakeUtils.SetDvdNav(useDvdNav);

				this.instance = new HandBrakeInstance();
				this.instance.Initialize(verbosity);

				this.instance.ScanCompleted += (o, e) =>
					{
						try
						{
							Title encodeTitle = this.instance.Titles.FirstOrDefault(title => title.TitleNumber == job.Title);

							if (encodeTitle != null)
							{
								lock (this.encodeLock)
								{
									this.instance.StartEncode(job, preview, previewNumber, previewSeconds, overallSelectedLengthSeconds, previewCount);
									this.callback.OnEncodeStarted();
									this.state = EncodeState.Encoding;
								}
							}
							else
							{
								this.callback.OnEncodeComplete(true);
								this.CleanUpAndSignalCompletion();
							}
						}
						catch (Exception exception)
						{
							this.callback.OnException(exception.ToString());
							this.CleanUpAndSignalCompletion();
						}
					};

				this.instance.EncodeProgress += (o, e) =>
					{
						this.StopOnException(() =>
							{
								this.callback.OnEncodeProgress(e.AverageFrameRate, e.CurrentFrameRate, e.EstimatedTimeLeft, e.FractionComplete, e.Pass);
							});
					};

				this.instance.EncodeCompleted += (o, e) =>
					{
						this.state = EncodeState.Finished;

						try
						{
							this.callback.OnEncodeComplete(e.Error);
						}
						catch (CommunicationException exception)
						{
							WorkerLogger.Log("Got exception when reporting completion: " + exception, isError: true);
						}
						finally
						{
							this.CleanUpAndSignalCompletion();
						}
					};

				this.instance.StartScan(job.SourcePath, previewCount, job.Title);
				this.state = EncodeState.Scanning;
			}
			catch (Exception exception)
			{
				this.callback.OnException(exception.ToString());
				throw;
			}
		}