/// <summary> /// Encodes a video and audio file. /// </summary> /// <param name="id">An ID used to track the item being encoded.</param> /// <param name="preset">The preset used to encode the given file.</param> /// <param name="file">The location of the file to encode.</param> /// <param name="command">The command used to tell Handbrake how to encode the video.</param> /// <param name="progress">The callback function fired when progress of a file's encoding is updated. The action is given the percentage complete.</param> /// <param name="complete">The callback function fired when encoding is complete. The action is given the location of the encoded file.</param> /// <returns>An ID used to track the item being encoded.</returns> public void Encode(Guid id, Preset preset, string file, string command, Action<EncodingMovieTask, double> progress, Action<EncodingMovieTask> complete) { if (string.IsNullOrEmpty(file)) throw new ArgumentNullException("file"); if (!System.IO.File.Exists(file)) throw new FileNotFoundException(file); command = string.Format(command, "\"" + file + "\"", id.ToString("N") + ".mp4" + PresetIndicator.Get(preset)); var task = new EncodingMovieTask {ID = id, File = file, PercentComplete = 0}; Logger.Info("Beginning encoding: " + command); new Thread(() => { var process = new Process(); process.StartInfo.FileName = @"c:\Code\showveoservice\ShowveoService.MVCApplication\Resources\HandbrakeCLI.exe"; process.StartInfo.Arguments = command; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.UseShellExecute = false; process.OutputDataReceived += (sender, args) => OnDataReceived(progress, task, args); process.ErrorDataReceived += (sender, args) => OnErrorReceived(args); process.Exited += (sender, args) => complete.Invoke(task); process.Start(); process.BeginOutputReadLine(); while (!process.HasExited) {} }).Start(); }
/// <summary> /// Adds or updates the encoding movie task to the progress list. /// </summary> /// <param name="task">The task to add or update.</param> /// <param name="percentChanged">The amount by which the task has completed.</param> public void AddOrUpdate(EncodingMovieTask task, double percentChanged = 0) { if (!_progress.ContainsKey(task.ID)) _progress[task.ID] = task; _progress[task.ID].PercentComplete += percentChanged; if (_progress[task.ID].PercentComplete > 100) _progress[task.ID].PercentComplete = 100; _pusher.Push(_progress[task.ID]); }
/// <summary> /// Fired after data has been received from an encoding operation /// </summary> private void OnDataReceived(Action<EncodingMovieTask, double> progress, EncodingMovieTask task, DataReceivedEventArgs e) { if (e.Data == null || !e.Data.Contains("%")) return; var begin = e.Data.IndexOf(",") + 1; var end = e.Data.IndexOf("%") - 1; var newPercent = Convert.ToDouble(e.Data.Substring(begin, end - begin).Replace(" ", "")); progress.Invoke(task, newPercent - _previousPercentage); _previousPercentage = newPercent; }
/// <summary> /// Pushes information regarding the progress of an encoding movie task. /// </summary> /// <param name="task">The encoding movie task.</param> public void Push(EncodingMovieTask task) { if (task == null) throw new ArgumentNullException("task"); _publisher.Publish(new Publication { Channel = _channel, DataJson = _serializer.Serialize(new { task.ID, File = Path.GetFileName(task.File), task.PercentComplete })}); }
/// <summary> /// Encodes a file. /// </summary> /// <param name="file">The file to encode.</param> /// <returns>The ID of the encoding task.</returns> public void Encode(string file) { if (string.IsNullOrEmpty(file)) throw new ArgumentNullException("file"); if (!System.IO.File.Exists(file)) throw new FileNotFoundException(file); var id = Guid.NewGuid(); var tasks = _factory.CreateAll().Select(localEncoder => (Action) (() => localEncoder.Encode(id, file, OnProgressReceived, OnEncodingCompleted))).ToList(); var task = new EncodingMovieTask {File = file, ID = id, PercentComplete = 0}; _encodingProgressContainer.AddOrUpdate(task); if (_queue.Count() == 0) tasks.First().Invoke(); _queue.Add(tasks); }
/// <summary> /// Fired after progress has been received for an encoding operation. /// </summary> /// <param name="task">The encoding movie task for which progress should be updated.</param> /// <param name="percentChanged">The amount by which the task has completed.</param> private void OnProgressReceived(EncodingMovieTask task, double percentChanged) { percentChanged /= _factory.EncoderCount; _encodingProgressContainer.AddOrUpdate(task, percentChanged); }
/// <summary> /// Fired after an encoding task has been completed. /// </summary> /// <param name="task">The completed task.</param> private void OnEncodingCompleted(EncodingMovieTask task) { var tasks = _queue[0]; tasks.RemoveAt(0); if (tasks.Count > 0) { tasks.First().Invoke(); return; } _encodingProgressContainer.AddOrUpdate(task, 100); _uncategorizedMovieRepository.Insert(new UncategorizedMovie { OriginalFile = task.File, EncodedFile = task.ID.ToString("N") }); _queue.RemoveAt(0); if (_queue.Count > 0) { tasks = _queue[0]; tasks.First().Invoke(); } }