Added command-line argument and more complex profiles.txt parsing
+using System;
+using System.Collections;
+
+public class EncoderProfile {
+ private string title;
+ public string Extension;
+ public ArrayList Steps;
+
+ public EncoderProfile(string title) {
+ this.title = title;
+ Extension = "mp4";
+ Steps = new ArrayList();
+ }
+
+ public string Title {
+ get { return title; }
+ }
+
+ public void AddStep(string step) {
+ Steps.Add(step);
+ }
+
+ public void SetOption(string key, string value) {
+ switch(key) {
+ case "extension":
+ Extension = value;
+ break;
+ default:
+ Console.WriteLine("Unknown profile option {0}", key);
+ break;
+ }
+ }
+}
CSLIBS = -debug -pkg:gtk-sharp-2.0
+objects = VFSEncoder.cs EncoderProfile.cs
all: VFSEncoder.exe
-%.exe: %.cs
- gmcs $(CSLIBS) $< -out:$@
+package: VFSEncoder.zip
+
+VFSEncoder.exe: $(objects)
+ gmcs $(CSLIBS) $^ -out:$@
+
+VFSEncoder.zip: VFSEncoder.exe profiles.txt
+ zip -9r VFSEncoder.zip VFSEncoder.exe profiles.txt
+
using System;
using System.Threading;
using System.IO;
+ using System.Reflection;
using System.Collections;
using System.Diagnostics;
using System.Text.RegularExpressions;
public class VFSEncoder {
- static ArrayList encoder_names;
- static ArrayList encoder_commands;
+ static ArrayList EncoderProfiles;
static Window window;
static Table options;
static bool cancel_encode = false;
- static void load_encoder_commands() {
- encoder_names = new ArrayList();
- encoder_commands = new ArrayList();
- StreamReader r = new StreamReader("profiles.txt");
- Regex section_re = new Regex(@"^\[(.+)\]$");
- ArrayList current = null;
+ static void fatal_error(string msg) {
+ MessageDialog d = new MessageDialog(null, DialogFlags.Modal, MessageType.Error, ButtonsType.Close, msg);
+ d.Title = "Error";
+ d.Run();
+ d.Destroy();
+ Environment.Exit(1);
+ }
+
+ static void LoadEncoderProfiles() {
+ EncoderProfiles = new ArrayList();
+ EncoderProfile current = null;
+
+ StreamReader r = null;
+ try {
+ r = new StreamReader("profiles.txt");
+ } catch (FileNotFoundException) {
+ fatal_error("Could not open profiles.txt");
+ }
+ Regex section_re = new Regex(@"^\[(.+)\]\s*(.*)$");
+ Regex option_re = new Regex(@"(?:(\w+)\s*:\s*(\w+)\s*)");
string line;
try {
Match m = section_re.Match(line);
if (m.Success) {
- Console.WriteLine(m.Groups[1].ToString());
- encoder_names.Add(m.Groups[1].ToString());
- current = new ArrayList();
- encoder_commands.Add(current);
+ string title = m.Groups[1].ToString();
+ string args = m.Groups[2].ToString();
+ current = new EncoderProfile(title);
+ //Console.WriteLine("\n[" + title + "]");
+ if (args != "") {
+ m = option_re.Match(args);
+ while (m.Success) {
+ //Console.WriteLine(m.Groups[1].Value + " => " + m.Groups[2].Value);
+ current.SetOption(m.Groups[1].Value, m.Groups[2].Value);
+ m = m.NextMatch();
+ }
+ }
+ EncoderProfiles.Add(current);
} else {
if (current != null) {
- Console.WriteLine("args: {0}", line);
- current.Add(line);
+ //Console.WriteLine(line);
+ current.AddStep(line);
+ } else {
+ Console.WriteLine("args before profile! : {0}", line);
}
}
}
static void stop_click(object obj, EventArgs args) {
p.StandardInput.Write("q");
p.StandardInput.Flush();
+ Thread.Sleep(50); // Wait for ffmpeg to listen
+ p.Kill();
p.WaitForExit();
cancel_encode = true;
}
go.Visible = false;
stop.Visible = true;
- string outfile = Path.Combine("output", Path.ChangeExtension(Path.GetFileName(browse.Filename), "mp4"));
+ EncoderProfile ep = (EncoderProfile) EncoderProfiles[profiles.Active];
+
+ string outfile = Path.Combine("output", Path.ChangeExtension(Path.GetFileName(browse.Filename), ep.Extension));
- foreach (string ffargs in (ArrayList)encoder_commands[profiles.Active]) {
+ foreach (string ffargs in ep.Steps) {
p = new Process();
p.StartInfo.FileName = "ffmpeg";
p.StartInfo.Arguments = String.Format("-y -i \"{0}\" {2} \"{1}\"", browse.Filename, outfile, ffargs);
public static int Main(string[] args) {
FileFilter filter;
- load_encoder_commands();
- if (encoder_commands.Count == 0) {
- Console.WriteLine("Couldn't find any encoder commands. Do you have profiles.txt?");
- return 1;
- }
+ string appdir;
+
+ appdir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+ Directory.SetCurrentDirectory(appdir);
Application.Init();
+ LoadEncoderProfiles();
+ if (EncoderProfiles.Count == 0) {
+ fatal_error("Couldn't find any encoder commands. Do you have profiles.txt?");
+ }
+
window = new Window("VFS Encoder");
window.DeleteEvent += delete_event;
window.DefaultWidth = 300;
filter.AddPattern("*.mov");
filter.AddMimeType("video/x-ms-wmv");
filter.AddPattern("*.wmv");
+ filter.AddPattern("*.asf");
filter.AddMimeType("video/mpeg");
filter.AddPattern("*.mpg");
+ filter.AddPattern("*.vob");
+ filter.AddPattern("*.mpeg");
+ filter.AddPattern("*.mp2v");
+ filter.AddMimeType("video/x-flv");
+ filter.AddPattern("*.flv");
filechooser.AddFilter(filter);
filter = new FileFilter();
browse = new FileChooserButton(filechooser);
options.Attach(browse, 1, 2, 0, 1);
profiles = ComboBox.NewText();
- foreach (string k in encoder_names)
- profiles.AppendText(k);
+ foreach (EncoderProfile ep in EncoderProfiles)
+ profiles.AppendText(ep.Title);
profiles.Active = 0;
options.Attach(profiles, 1, 2, 1, 2);
go = new Button("Go!");
status.Justify = Justification.Left;
status.Text = "VFSEncoder Ready";
+ if (args.Length == 1) {
+ browse.SetFilename(args[0]);
+ Console.WriteLine("Set filename to " + args[0]);
+ }
+
window.Add(options);
options.Show();
window.ShowAll();
+[DVD VOB => MPEG2 TS +deinterlace] extension:mpeg foo:bar baz:quux
+-vcodec mpeg2video -vb 5000k -acodec copy -s 640x480 -deinterlace -f mpegts
+
[x264 lossless]
--vcodec h264 -cqp 0
+-vcodec libx264 -cqp 0
-[xvid q=1]
--vcodec xvid -qscale 1
+[XviD q=1]
+-vcodec libxvid -qscale 1
-[xvid 1500kbit 2pass]
--vcodec xvid -flags +trell+aic+4mv -b 1500k -an -pass 1
--vcodec xvid -flags +trell+aic+4mv -b 1500k -acodec aac -ab 128k -ar 22050 -pass 2
+[XviD 1500kbit 2pass]
+-vcodec libxvid -flags +trell+aic+4mv -b 1500k -an -pass 1
+-vcodec libxvid -flags +trell+aic+4mv -b 1500k -acodec libfaac -ab 128k -ar 22050 -pass 2
[x264 1500kbit 2pass]
--vcodec x264 -qmax 50 -coder 1 -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -me hex -subq 5 -me_range 16 -g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -b_strategy 1 -b 1500k -an -pass 1
--vcodec x264 -qmax 50 -coder 1 -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -me hex -subq 5 -me_range 16 -g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -b_strategy 1 -b 1500k -acodec aac -ab 128k -ar 22050 -pass 2
+-vcodec libx264 -b 1500k -bt 1500k -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 -coder 1 -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -me hex -subq 5 -me_range 16 -g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -b_strategy 1 -an -pass 1
+-vcodec libx264 -b 1500k -bt 1500k -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 -qmax 50 -coder 1 -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -me hex -subq 5 -me_range 16 -g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -b_strategy 1 -acodec libfaac -ab 128k -ar 22050 -pass 2