]> git.sesse.net Git - x264/commitdiff
GTK-based graphical frontend.
authorLoren Merritt <pengvado@videolan.org>
Sat, 25 Mar 2006 10:13:12 +0000 (10:13 +0000)
committerLoren Merritt <pengvado@videolan.org>
Sat, 25 Mar 2006 10:13:12 +0000 (10:13 +0000)
patch by Vincent Torri.

git-svn-id: svn://svn.videolan.org/x264/trunk@481 df754926-b1dd-0310-bc7b-ec298dee348c

24 files changed:
AUTHORS
gtk/Makefile [new file with mode: 0644]
gtk/test.c [new file with mode: 0644]
gtk/x264.png [new file with mode: 0644]
gtk/x264_gtk.c [new file with mode: 0644]
gtk/x264_gtk.h [new file with mode: 0644]
gtk/x264_gtk_bitrate.c [new file with mode: 0644]
gtk/x264_gtk_bitrate.h [new file with mode: 0644]
gtk/x264_gtk_encode.c [new file with mode: 0644]
gtk/x264_gtk_encode_encode.c [new file with mode: 0644]
gtk/x264_gtk_encode_encode.h [new file with mode: 0644]
gtk/x264_gtk_encode_main_window.c [new file with mode: 0644]
gtk/x264_gtk_encode_main_window.h [new file with mode: 0644]
gtk/x264_gtk_encode_private.h [new file with mode: 0644]
gtk/x264_gtk_encode_status_window.c [new file with mode: 0644]
gtk/x264_gtk_encode_status_window.h [new file with mode: 0644]
gtk/x264_gtk_enum.h [new file with mode: 0644]
gtk/x264_gtk_mb.c [new file with mode: 0644]
gtk/x264_gtk_mb.h [new file with mode: 0644]
gtk/x264_gtk_more.c [new file with mode: 0644]
gtk/x264_gtk_more.h [new file with mode: 0644]
gtk/x264_gtk_private.h [new file with mode: 0644]
gtk/x264_gtk_rc.c [new file with mode: 0644]
gtk/x264_gtk_rc.h [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index f61939a94644758bd5482122e863ecbc4f317513..b0baad182650fbf47df385fa88dfc17c5010d694 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -97,3 +97,7 @@ N: Tuukka Toivonen
 E: tuukkat AT ee DOT oulu DOT fi
 D: Visualization
 
+N: Vincent Torri
+E: Vincent DOT Torri AT iecn DOT u-nancy DOT fr
+D: GTK frontend
+
diff --git a/gtk/Makefile b/gtk/Makefile
new file mode 100644 (file)
index 0000000..1de6931
--- /dev/null
@@ -0,0 +1,79 @@
+
+include ../config.mak
+
+datadir=${prefix}/share/x264
+
+OBJECTS = x264_gtk_bitrate.o x264_gtk_rc.o x264_gtk_mb.o x264_gtk_more.o x264_gtk.o
+
+TEST_OBJECT = test.o
+ENCODE_OBJECT = x264_gtk_encode_encode.o x264_gtk_encode_status_window.o x264_gtk_encode_main_window.o x264_gtk_encode.o
+
+CC = gcc
+
+all: x264_gtk_encode test
+
+CPPFLAGS = `pkg-config --cflags gtk+-2.0 gthread-2.0 x264` -DX264_DATA_DIR=\"${datadir}\"
+CFLAGS = -O2 -Wall -W
+LDFLAGS += `pkg-config --libs gtk+-2.0 gthread-2.0 x264` -lpthread
+
+# Compilation rule
+%.o : %.c
+       @echo "  C: $(@D)/$(<F)"
+       @$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
+
+# Linking rule
+libx264gtk.a: $(OBJECTS)
+       @echo "  L: $(@F)"
+       @ar rc libx264gtk.a $(OBJECTS)
+       @ranlib libx264gtk.a
+
+test: $(OBJECTS) $(TEST_OBJECT)
+       @echo "  B: $(@F)"
+       @$(CC) -o test $(OBJECTS) $(TEST_OBJECT) $(LDFLAGS)
+
+x264_gtk_encode: $(OBJECTS) libx264gtk.a $(ENCODE_OBJECT)
+       @echo "  B: $(@F)"
+       @$(CC) -o x264_gtk_encode $(OBJECTS) $(ENCODE_OBJECT) ../muxers.o ../matroska.o $(LDFLAGS)
+
+# Clean rule
+clean:
+       @rm -f *o test x264_gtk_encode libx264gtk.a
+
+# Install rule
+install: x264_gtk_encode
+       @echo "  I: $(DESTDIR)$(includedir)/x264_gtk.h"
+       @install -m 644 x264_gtk.h $(DESTDIR)$(includedir)
+       @echo "  I: $(DESTDIR)$(includedir)/x264_gtk_enum.h"
+       @install -m 644 x264_gtk_enum.h $(DESTDIR)$(includedir)
+       @echo "  I: $(DESTDIR)$(libdir)/libx264gtk.a"
+       @install -m 644 libx264gtk.a $(DESTDIR)$(libdir)
+       @echo "  I: $(DESTDIR)$(bindir)/x264_gtk_encode"
+       @install x264_gtk_encode $(DESTDIR)$(bindir)
+       @echo "  D: $(DESTDIR)$(datadir)"
+       @install -d $(DESTDIR)$(datadir)
+       @echo "  I: $(DESTDIR)$(datadir)/x264.png"
+       @install -m 644 x264.png $(DESTDIR)$(datadir)
+
+# Uninstall rule
+uninstall:
+       @echo "  U: $(DESTDIR)$(includedir)/x264_gtk.h"
+       @rm -f $(DESTDIR)$(includedir)/x264_gtk.h
+       @echo "  U: $(DESTDIR)$(includedir)/x264_gtk_enum.h"
+       @rm -f $(DESTDIR)$(includedir)/x264_gtk_enum.h
+       @echo "  U: $(DESTDIR)$(libdir)/libx264gtk.a"
+       @rm -f $(DESTDIR)$(libdir)/libx264gtk.a
+       @echo "  U: $(DESTDIR)$(bindir)/x264_gtk_encode"
+       @rm -f $(DESTDIR)$(bindir)/x264_gtk_encode
+       @echo "  U: $(DESTDIR)$(datadir)"
+       @rm -rf $(DESTDIR)$(datadir)
+
+x264_gtk_bitrate.o: x264_gtk_bitrate.h x264_gtk_bitrate.c
+x264_gtk_rc.o: x264_gtk_rc.h x264_gtk_rc.c
+x264_gtk_mb.o: x264_gtk_mb.h x264_gtk_mb.c
+x264_gtk_more.o: x264_gtk_more.h x264_gtk_more.c
+gtk_x264.o: x264_gtk.h x264_gtk.c
+gtk_x264_encode_encode.o: x264_gtk.o x264_gtk_encode_encode.c
+gtk_x264_encode_status_window.o: x264_gtk.o x264_gtk_encode_status_window.c
+gtk_x264_encode_main_window.o: x264_gtk.o x264_gtk_encode_main_window.c
+gtk_x264_encode.o: x264_gtk.o x264_gtk_encode_encode.c x264_gtk_encode_status_window.c x264_gtk_encode_main_window.c x264_gtk_encode.c
+test.o: x264_gtk.o test.c
diff --git a/gtk/test.c b/gtk/test.c
new file mode 100644 (file)
index 0000000..1e9da7c
--- /dev/null
@@ -0,0 +1,53 @@
+#include <stdint.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#       define DECLARE_ALIGNED( type, var, n ) type var __attribute__((aligned(n)))
+#include "../common/common.h"
+#include "../x264.h"
+#include "x264_gtk.h"
+
+
+int
+main (int argc, char *argv[])
+{
+  GtkWidget    *window;
+  X264_Gtk     *x264_gtk;
+  x264_param_t *param;
+  x264_param_t  param_default;
+  char         *res;
+  char         *res_default;
+
+  gtk_init (&argc, &argv);
+  
+  window = x264_gtk_window_create (NULL);
+  x264_gtk_shutdown (window);
+
+  x264_gtk = x264_gtk_load ();
+  param = x264_gtk_param_get (x264_gtk);
+
+  /* do what you want with these data */
+  /* for example, displaying them and compare with default*/
+  res = x264_param2string (param, 0);
+  printf ("%s\n", res);
+
+  x264_param_default (&param_default);
+  res_default = x264_param2string (&param_default, 0);
+  printf ("\n%s\n", res_default);
+
+  if (strcmp (res, res_default) == 0)
+    printf ("\nSame result !\n");
+  else
+    printf ("\nDifferent from default values\n");
+
+  x264_free (res);
+  x264_free (res_default);
+
+  g_free (x264_gtk);
+  g_free (param);
+
+  gtk_main_quit ();
+
+  return 1;
+}
diff --git a/gtk/x264.png b/gtk/x264.png
new file mode 100644 (file)
index 0000000..ca2ada8
Binary files /dev/null and b/gtk/x264.png differ
diff --git a/gtk/x264_gtk.c b/gtk/x264_gtk.c
new file mode 100644 (file)
index 0000000..49b94f0
--- /dev/null
@@ -0,0 +1,869 @@
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <math.h>
+#if defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ || defined __DragonFly__
+#  include <inttypes.h>
+#else
+#  include <stdint.h>
+#endif
+#ifdef _WIN32
+#  include <unistd.h>  /* for mkdir */
+#endif
+
+#include <x264.h>
+
+#include <gtk/gtk.h>
+
+#include "x264_gtk.h"
+#include "x264_gtk_private.h"
+#include "x264_gtk_enum.h"
+#include "x264_gtk_bitrate.h"
+#include "x264_gtk_rc.h"
+#include "x264_gtk_mb.h"
+#include "x264_gtk_more.h"
+
+
+#define CHECK_FLAG(a,flag) ((a) & (flag)) == (flag)
+#define round(a) ( ((a)<0.0) ? (gint)(floor((a) - 0.5)) : (gint)(floor((a) + 0.5)) )
+
+/* Callbacks */
+static void _dialog_run (GtkDialog       *dialog,
+                         gint             response,
+                         X264_Gui_Config *gconfig,
+                         X264_Gtk        *x264_gtk);
+
+
+/* x264 config management */
+static void _default_load (GtkButton *button, gpointer user_data);
+static void _current_get (X264_Gui_Config *gconfig, X264_Gtk *x264_gtk);
+static void _current_set (X264_Gui_Config *gconfig, X264_Gtk *x264_gtk);
+static void _default_set (X264_Gtk *x264_gtk);
+
+
+/* Result must be freed */
+x264_param_t *x264_gtk_param_get (X264_Gtk *x264_gtk)
+{
+  x264_param_t *param;
+
+  if (!x264_gtk)
+    return NULL;
+
+  param = (x264_param_t *)g_malloc (sizeof (x264_param_t));
+  if (!param)
+    return NULL;
+
+  x264_param_default (param);
+
+  /* bitrate */
+  if (x264_gtk->pass == X264_PASS_SINGLE_BITRATE)
+    param->rc.i_bitrate  = x264_gtk->average_bitrate;
+  else
+    param->rc.i_bitrate = x264_gtk->target_bitrate;
+  param->rc.i_qp_constant = x264_gtk->quantizer;
+
+  /* FIXME: what to do about psz_stat_out ? */
+
+  /* rate control */
+  param->rc.f_ip_factor = 1.0 + (double)x264_gtk->keyframe_boost / 100.0;
+  param->rc.f_pb_factor = 1.0 + (double)x264_gtk->bframes_reduction / 100.0;
+  param->rc.f_qcompress = (double)x264_gtk->bitrate_variability / 100.0;
+
+  param->rc.i_qp_min = x264_gtk->min_qp;
+  param->rc.i_qp_max = x264_gtk->max_qp;
+  param->rc.i_qp_step = x264_gtk->max_qp_step;
+
+  param->i_scenecut_threshold = x264_gtk->scene_cut_threshold;
+  param->i_keyint_min = x264_gtk->min_idr_frame_interval;
+  param->i_keyint_max = x264_gtk->max_idr_frame_interval;
+
+  /* mb */
+  param->analyse.b_transform_8x8 = x264_gtk->transform_8x8;
+  param->analyse.inter = 0;
+  if (x264_gtk->pframe_search_8)
+    param->analyse.inter |= X264_ANALYSE_PSUB16x16;
+  if (x264_gtk->bframe_search_8)
+    param->analyse.inter |= X264_ANALYSE_BSUB16x16;
+  if (x264_gtk->pframe_search_4)
+    param->analyse.inter |= X264_ANALYSE_PSUB8x8;
+  if (x264_gtk->inter_search_8)
+    param->analyse.inter |= X264_ANALYSE_I8x8;
+  if (x264_gtk->inter_search_4)
+    param->analyse.inter |= X264_ANALYSE_I4x4;
+
+  param->i_bframe = x264_gtk->use_as_reference;
+  param->analyse.b_bidir_me = x264_gtk->bidir_me;
+  param->b_bframe_adaptive = x264_gtk->adaptive;
+  if ((x264_gtk->use_as_reference > 1) && x264_gtk->weighted_biprediction)
+    param->analyse.b_weighted_bipred = 1;
+  else
+    param->analyse.b_weighted_bipred = 0;
+  /* not used: */
+  /* x264_gtk->max_consecutive; */
+  param->i_bframe_bias = x264_gtk->bias;
+  param->analyse.i_direct_mv_pred = x264_gtk->direct_mode;
+
+  /* more */
+  param->analyse.i_subpel_refine = x264_gtk->partition_decision + 1;
+  param->analyse.b_bframe_rdo = x264_gtk->bframe_rdo;
+  param->analyse.i_me_method = x264_gtk->me_method;
+  param->analyse.i_me_range = x264_gtk->range;
+  param->analyse.b_chroma_me = x264_gtk->chroma_me;
+  param->analyse.i_trellis = x264_gtk->trellis;
+  param->analyse.i_noise_reduction = x264_gtk->noise_reduction;
+  param->i_frame_reference = x264_gtk->max_ref_frames;
+  param->analyse.b_mixed_references = x264_gtk->mixed_refs;
+
+  param->vui.i_sar_width = x264_gtk->sample_ar_x;
+  param->vui.i_sar_height = x264_gtk->sample_ar_y;
+  param->i_threads = x264_gtk->threads;
+  param->b_cabac = x264_gtk->cabac;
+  param->b_deblocking_filter = x264_gtk->deblocking_filter;
+  param->i_deblocking_filter_alphac0 = x264_gtk->strength;
+  param->i_deblocking_filter_beta = x264_gtk->threshold;
+
+  param->i_log_level = x264_gtk->debug_method - 1;
+
+  return param;
+}
+
+/* Result must be freed */
+X264_Gtk *
+x264_gtk_load (void)
+{
+  X264_Gtk     *x264_gtk;
+  GIOChannel   *file;
+  GError       *error = NULL;
+  gchar        *filename;
+
+  x264_gtk = (X264_Gtk *)g_malloc0 (sizeof (X264_Gtk));
+  if (!x264_gtk)
+    return NULL;
+
+  filename = g_build_filename (g_get_home_dir (),
+                               ".x264",
+                               "/x264.cfg",
+                               NULL);
+  file = g_io_channel_new_file (filename, "r", &error);
+  if (error)
+    {
+      g_print ("x264.cfg: %s\n", error->message);
+      g_print ("Loading default configuration\n");
+      _default_set (x264_gtk);
+    }
+  else
+    {
+      GIOStatus status;
+      gchar    *data = NULL;
+      gsize     length;
+
+      g_print ("Loading configuration from %s\n", filename);
+      g_io_channel_set_encoding (file, NULL, NULL);
+      status = g_io_channel_read_to_end (file, &data, &length, &error);
+      if ((status == G_IO_STATUS_NORMAL) &&
+          (length == sizeof (X264_Gtk)))
+        {
+          memcpy (x264_gtk, data, length);
+        }
+      g_io_channel_shutdown (file, TRUE, NULL);
+      g_io_channel_unref (file);
+    }
+  g_free (filename);
+
+  return x264_gtk;
+}
+
+GtkWidget *
+x264_gtk_window_create (GtkWidget *parent)
+{
+  GtkWidget       *win_x264_gtk;
+  GtkWidget       *notebook;
+  GtkWidget       *page;
+  GtkWidget       *button;
+  GtkWidget       *label;
+  X264_Gui_Config *gconfig;
+  X264_Gtk        *x264_gtk;
+  gint             result;
+  GtkDialogFlags   flags = 0;
+
+  gconfig = (X264_Gui_Config *)g_malloc (sizeof (X264_Gui_Config));
+  if (!gconfig)
+    return NULL;
+
+  x264_gtk = x264_gtk_load ();
+
+  if (parent)
+    flags = GTK_DIALOG_MODAL |GTK_DIALOG_DESTROY_WITH_PARENT;
+  win_x264_gtk = gtk_dialog_new_with_buttons ("X264 Configuration",
+                                              GTK_WINDOW (parent),
+                                              flags,
+                                              NULL);
+
+  button = gtk_button_new_with_label ("Default");
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (win_x264_gtk)->action_area), button, FALSE, TRUE, 6);
+  g_signal_connect (G_OBJECT (button),
+                    "clicked",
+                    G_CALLBACK (_default_load),
+                    gconfig);
+  gtk_widget_show (button);
+
+  gtk_dialog_add_buttons (GTK_DIALOG (win_x264_gtk),
+                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                          GTK_STOCK_OK, GTK_RESPONSE_OK,
+                          NULL);
+
+  g_object_set_data (G_OBJECT (win_x264_gtk), "x264-gui-config", gconfig);
+  g_object_set_data (G_OBJECT (win_x264_gtk), "x264-config", x264_gtk);
+  gtk_window_set_resizable (GTK_WINDOW (win_x264_gtk), FALSE);
+
+  notebook = gtk_notebook_new ();
+  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (win_x264_gtk)->vbox), notebook);
+  gtk_widget_show (notebook);
+
+  label = gtk_label_new ("Bitrate");
+  gtk_widget_show (label);
+
+  page = _bitrate_page (gconfig);
+  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, label);
+  gtk_widget_show (page);
+
+  label = gtk_label_new ("Rate Control");
+  gtk_widget_show (label);
+
+  page = _rate_control_page (gconfig);
+  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, label);
+  gtk_widget_show (page);
+
+  label = gtk_label_new ("MB & Frames");
+  gtk_widget_show (label);
+
+  page = _mb_page (gconfig);
+  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, label);
+  gtk_widget_show (page);
+
+  label = gtk_label_new ("More...");
+  gtk_widget_show (label);
+
+  page = _more_page (gconfig);
+  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, label);
+  gtk_widget_show (page);
+
+  _current_set (gconfig, x264_gtk);
+
+  result = gtk_dialog_run (GTK_DIALOG (win_x264_gtk));
+  _dialog_run (GTK_DIALOG (win_x264_gtk), result, gconfig, x264_gtk);
+
+  return win_x264_gtk;
+}
+
+void
+x264_gtk_shutdown (GtkWidget *dialog)
+{
+  X264_Gui_Config *gconfig;
+
+  gconfig = g_object_get_data (G_OBJECT (dialog), "x264-gui-config");
+  gtk_widget_destroy (dialog);
+  if (gconfig)
+    g_free (gconfig);
+}
+
+
+/* Notebook pages */
+
+/* Callbacks */
+
+static void
+_dialog_run (GtkDialog       *dialog __UNUSED__,
+             gint             response,
+             X264_Gui_Config *gconfig,
+             X264_Gtk        *x264_gtk)
+{
+  if (response == GTK_RESPONSE_OK)
+    {
+      GIOChannel *file;
+      gchar      *filename;
+      gchar      *dir;
+      gsize       length;
+      gint        res;
+#ifndef _WIN32
+      mode_t      mode;
+#endif
+
+      dir = g_build_filename (g_get_home_dir (),
+                              ".x264",
+                              NULL);
+#ifdef _WIN32
+      res = mkdir (dir);
+#else
+      mode =
+        S_IRUSR | S_IXUSR | S_IWUSR |
+        S_IRGRP | S_IXGRP | S_IWGRP |
+        S_IROTH | S_IXOTH | S_IWOTH;
+      res = mkdir (dir, mode);
+#endif /* _WIN32 */
+      if (res != 0 && errno != EEXIST)
+        {
+          g_free (dir);
+
+          return;
+        }
+      filename = g_build_filename (g_get_home_dir (),
+                                   ".x264",
+                                   "x264.cfg",
+                                   NULL);
+      g_print ("Writing configuration to %s\n", filename);
+      file = g_io_channel_new_file (filename,
+                                    "w+", NULL);
+      if (file)
+        {
+          _current_get (gconfig, x264_gtk);
+          g_io_channel_set_encoding (file, NULL, NULL);
+          g_io_channel_write_chars (file, (const gchar *)x264_gtk,
+                                    sizeof (X264_Gtk), &length, NULL);
+          g_io_channel_unref (file);
+        }
+      g_free (filename);
+      g_free (dir);
+    }
+}
+
+/* x264 config management */
+static void
+_default_load (GtkButton *button __UNUSED__, gpointer user_data)
+{
+  X264_Gui_Config *config;
+  x264_param_t     param;
+  gchar            buf[64];
+
+  if (!user_data)
+    return;
+
+  config = (X264_Gui_Config *)user_data;
+
+  x264_param_default (&param);
+
+  /* bitrate */
+  gtk_combo_box_set_active (GTK_COMBO_BOX (config->bitrate.pass), 1);
+  g_print ("bitrate %d\n", param.rc.i_bitrate);
+  g_snprintf (buf, 64, "%d", param.rc.i_bitrate);
+  gtk_entry_set_text (GTK_ENTRY (config->bitrate.w_average_bitrate), buf);
+  gtk_entry_set_text (GTK_ENTRY (config->bitrate.w_target_bitrate), buf);
+  gtk_range_set_range (GTK_RANGE (config->bitrate.w_quantizer),
+                       (gdouble)param.rc.i_qp_min,
+                       (gdouble)param.rc.i_qp_max);
+  gtk_range_set_value (GTK_RANGE (config->bitrate.w_quantizer),
+                       (gdouble)param.rc.i_qp_constant);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->bitrate.update_statfile), FALSE);
+  gtk_entry_set_text (GTK_ENTRY (config->bitrate.statsfile_name), "x264.stats");
+  gtk_widget_set_sensitive (config->bitrate.statsfile_name, FALSE);
+
+  /* rate control */
+  g_snprintf (buf, 64, "%d", round((param.rc.f_ip_factor - 1) * 100));
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.bitrate.keyframe_boost), buf);
+  g_snprintf (buf, 64, "%d", round((param.rc.f_pb_factor - 1) * 100));
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.bitrate.bframes_reduction), buf);
+  g_snprintf (buf, 64, "%d", (gint)(param.rc.f_qcompress * 100));
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.bitrate.bitrate_variability), buf);
+
+  g_snprintf (buf, 64, "%d", param.rc.i_qp_min);
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.quantization_limits.min_qp), buf);
+  g_snprintf (buf, 64, "%d", param.rc.i_qp_max);
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.quantization_limits.max_qp), buf);
+  g_snprintf (buf, 64, "%d", param.rc.i_qp_step);
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.quantization_limits.max_qp_step), buf);
+
+  g_snprintf (buf, 64, "%d", param.i_scenecut_threshold);
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.scene_cuts.scene_cut_threshold), buf);
+  g_snprintf (buf, 64, "%d", param.i_keyint_min);
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.scene_cuts.min_idr_frame_interval), buf);
+  g_snprintf (buf, 64, "%d", param.i_keyint_max);
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.scene_cuts.max_idr_frame_interval), buf);
+
+  /* mb */
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.transform_8x8), param.analyse.b_transform_8x8);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.pframe_search_8), CHECK_FLAG(param.analyse.inter, X264_ANALYSE_PSUB16x16));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.bframe_search_8), CHECK_FLAG(param.analyse.inter, X264_ANALYSE_BSUB16x16));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.pframe_search_4), CHECK_FLAG(param.analyse.inter, X264_ANALYSE_PSUB8x8));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.inter_search_8), CHECK_FLAG(param.analyse.inter, X264_ANALYSE_I8x8));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.inter_search_4), CHECK_FLAG(param.analyse.inter, X264_ANALYSE_I4x4));
+
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.bframes.use_as_reference), param.i_bframe);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.bframes.adaptive), param.b_bframe_adaptive);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.bframes.weighted_biprediction), param.analyse.b_weighted_bipred);
+  g_snprintf (buf, 64, "%d", param.b_bframe_adaptive);
+  gtk_entry_set_text (GTK_ENTRY (config->mb.bframes.max_consecutive), buf);
+  gtk_range_set_value (GTK_RANGE (config->mb.bframes.bias), (gdouble)param.i_bframe_bias);
+  gtk_combo_box_set_active (GTK_COMBO_BOX (config->mb.bframes.direct_mode), param.analyse.i_direct_mv_pred);
+
+  /* more */
+  if (param.analyse.b_bframe_rdo)
+    gtk_combo_box_set_active (GTK_COMBO_BOX (config->more.motion_estimation.partition_decision), X264_PD_6b);
+  else
+    gtk_combo_box_set_active (GTK_COMBO_BOX (config->more.motion_estimation.partition_decision), param.analyse.i_subpel_refine - 1);
+  gtk_combo_box_set_active (GTK_COMBO_BOX (config->more.motion_estimation.method), param.analyse.i_me_method);
+  g_snprintf (buf, 64, "%d", param.analyse.i_me_range);
+  gtk_entry_set_text (GTK_ENTRY (config->more.motion_estimation.range), buf);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->more.motion_estimation.chroma_me), param.analyse.b_chroma_me);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->more.motion_estimation.mixed_refs), param.analyse.b_mixed_references);
+  g_snprintf (buf, 64, "%d", param.i_frame_reference);
+  gtk_entry_set_text (GTK_ENTRY (config->more.motion_estimation.max_ref_frames), buf);
+
+  g_snprintf (buf, 64, "%d", param.vui.i_sar_width);
+  gtk_entry_set_text (GTK_ENTRY (config->more.misc.sample_ar_x), buf);
+  g_snprintf (buf, 64, "%d", param.vui.i_sar_height);
+  gtk_entry_set_text (GTK_ENTRY (config->more.misc.sample_ar_y), buf);
+  g_snprintf (buf, 64, "%d", param.i_threads);
+  gtk_entry_set_text (GTK_ENTRY (config->more.misc.threads), buf);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->more.misc.cabac), param.b_cabac);
+  gtk_combo_box_set_active (GTK_COMBO_BOX (config->more.misc.trellis), param.analyse.i_trellis);
+  g_snprintf (buf, 64, "%d", param.analyse.i_noise_reduction);
+  gtk_entry_set_text (GTK_ENTRY (config->more.misc.noise_reduction), buf);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->more.misc.df.deblocking_filter), param.b_deblocking_filter);
+  gtk_range_set_value (GTK_RANGE (config->more.misc.df.strength), (gdouble)param.i_deblocking_filter_alphac0);
+  gtk_range_set_value (GTK_RANGE (config->more.misc.df.threshold), (gdouble)param.i_deblocking_filter_beta);
+
+  gtk_combo_box_set_active (GTK_COMBO_BOX (config->more.debug.log_level), 1);
+  gtk_entry_set_text (GTK_ENTRY (config->more.debug.fourcc), "H264");
+}
+
+static void
+_default_set (X264_Gtk *x264_gtk)
+{
+  x264_param_t param;
+  gchar       *text;
+
+  x264_param_default (&param);
+
+  /* bitrate */
+  x264_gtk->pass = X264_PASS_SINGLE_QUANTIZER;
+  x264_gtk->average_bitrate = param.rc.i_bitrate;
+  x264_gtk->target_bitrate = param.rc.i_bitrate;
+  x264_gtk->quantizer = param.rc.i_qp_constant;
+  x264_gtk->update_statfile = 0;
+  text = "x264.stats";
+  memcpy (x264_gtk->statsfile_name, text, strlen (text) + 1);
+
+  /* rate control */
+  x264_gtk->keyframe_boost = round((param.rc.f_ip_factor - 1) * 100);
+  x264_gtk->bframes_reduction = round((param.rc.f_pb_factor - 1) * 100);
+  x264_gtk->bitrate_variability = round(param.rc.f_qcompress * 100);
+
+  x264_gtk->min_qp = param.rc.i_qp_min;
+  x264_gtk->max_qp = param.rc.i_qp_max;
+  x264_gtk->max_qp_step = param.rc.i_qp_step;
+
+  x264_gtk->scene_cut_threshold = param.i_scenecut_threshold;
+  x264_gtk->min_idr_frame_interval = param.i_keyint_min;
+  x264_gtk->max_idr_frame_interval = param.i_keyint_max;
+  x264_gtk->direct_mode = param.analyse.i_direct_mv_pred;
+
+  /* mb */
+  x264_gtk->transform_8x8 = param.analyse.b_transform_8x8;
+  x264_gtk->max_ref_frames = param.i_frame_reference;
+  x264_gtk->mixed_refs = param.analyse.b_mixed_references;
+
+  if (CHECK_FLAG(param.analyse.inter, X264_ANALYSE_PSUB16x16))
+    x264_gtk->pframe_search_8 = 1;
+  else
+    x264_gtk->pframe_search_8 = 0;
+  if (CHECK_FLAG(param.analyse.inter, X264_ANALYSE_BSUB16x16))
+    x264_gtk->bframe_search_8 = 1;
+  else
+    x264_gtk->bframe_search_8 = 0;
+  if (CHECK_FLAG(param.analyse.inter, X264_ANALYSE_PSUB8x8))
+    x264_gtk->pframe_search_4 = 1;
+  else
+    x264_gtk->pframe_search_4 = 0;
+  x264_gtk->inter_search_8 = CHECK_FLAG(param.analyse.inter, X264_ANALYSE_I8x8);
+  x264_gtk->inter_search_4 = CHECK_FLAG(param.analyse.inter, X264_ANALYSE_I4x4);
+
+  x264_gtk->use_as_reference = param.i_bframe;
+  x264_gtk->adaptive = param.b_bframe_adaptive;
+  x264_gtk->weighted_biprediction = param.analyse.b_weighted_bipred;
+  x264_gtk->max_consecutive = 0; /* not used */
+  x264_gtk->bias = param.i_bframe_bias;
+
+  /* more */
+  x264_gtk->bframe_rdo = param.analyse.b_bframe_rdo;
+  x264_gtk->partition_decision = param.analyse.i_subpel_refine - 1;
+  x264_gtk->me_method = param.analyse.i_me_method;
+  x264_gtk->range = param.analyse.i_me_range;
+  x264_gtk->chroma_me = param.analyse.b_chroma_me;
+
+  x264_gtk->sample_ar_x = param.vui.i_sar_width;
+  x264_gtk->sample_ar_y = param.vui.i_sar_height;
+  x264_gtk->threads = param.i_threads;
+  x264_gtk->cabac = param.b_cabac;
+  x264_gtk->trellis = param.analyse.i_trellis;
+  x264_gtk->noise_reduction = param.analyse.i_noise_reduction;
+  x264_gtk->deblocking_filter = param.b_deblocking_filter;
+  x264_gtk->strength = param.i_deblocking_filter_alphac0;
+  x264_gtk->threshold = param.i_deblocking_filter_beta;
+
+  x264_gtk->debug_method = X264_DEBUG_METHOD_ERROR;
+  text = "H264";
+  memcpy (x264_gtk->fourcc, text, strlen (text) + 1);
+}
+
+static void
+_current_set (X264_Gui_Config *config, X264_Gtk *x264_gtk)
+{
+  gchar buf[4096];
+
+  if (!config)
+    return;
+
+  /* bitrate */
+  gtk_combo_box_set_active (GTK_COMBO_BOX (config->bitrate.pass), x264_gtk->pass);
+  g_snprintf (buf, 5, "%d", x264_gtk->average_bitrate);
+  gtk_entry_set_text (GTK_ENTRY (config->bitrate.w_average_bitrate), buf);
+  gtk_range_set_value (GTK_RANGE (config->bitrate.w_quantizer), x264_gtk->quantizer);
+  g_snprintf (buf, 5, "%d", x264_gtk->target_bitrate);
+  gtk_entry_set_text (GTK_ENTRY (config->bitrate.w_target_bitrate), buf);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->bitrate.update_statfile), x264_gtk->update_statfile);
+  gtk_entry_set_text (GTK_ENTRY (config->bitrate.statsfile_name), x264_gtk->statsfile_name);
+  if (x264_gtk->update_statfile)
+    gtk_widget_set_sensitive (config->bitrate.statsfile_name, TRUE);
+  else
+    gtk_widget_set_sensitive (config->bitrate.statsfile_name, FALSE);
+
+  /* rate control */
+  g_snprintf (buf, 5, "%d", x264_gtk->keyframe_boost);
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.bitrate.keyframe_boost), buf);
+  g_snprintf (buf, 5, "%d", x264_gtk->bframes_reduction);
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.bitrate.bframes_reduction), buf);
+  g_snprintf (buf, 5, "%d", x264_gtk->bitrate_variability);
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.bitrate.bitrate_variability), buf);
+
+  g_snprintf (buf, 5, "%d", x264_gtk->min_qp);
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.quantization_limits.min_qp), buf);
+  g_snprintf (buf, 5, "%d", x264_gtk->max_qp);
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.quantization_limits.max_qp), buf);
+  g_snprintf (buf, 5, "%d", x264_gtk->max_qp_step);
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.quantization_limits.max_qp_step), buf);
+
+  g_snprintf (buf, 5, "%d", x264_gtk->scene_cut_threshold);
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.scene_cuts.scene_cut_threshold), buf);
+  g_snprintf (buf, 5, "%d", x264_gtk->min_idr_frame_interval);
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.scene_cuts.min_idr_frame_interval), buf);
+  g_snprintf (buf, 5, "%d", x264_gtk->max_idr_frame_interval);
+  gtk_entry_set_text (GTK_ENTRY (config->rate_control.scene_cuts.max_idr_frame_interval), buf);
+
+  /* mb */
+  if (x264_gtk->transform_8x8)
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.transform_8x8), TRUE);
+  else
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.transform_8x8), FALSE);
+  if (x264_gtk->pframe_search_8)
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.pframe_search_8), TRUE);
+  else
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.pframe_search_8), FALSE);
+  if (x264_gtk->bframe_search_8)
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.bframe_search_8), TRUE);
+  else
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.bframe_search_8), FALSE);
+  if (x264_gtk->pframe_search_4)
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.pframe_search_4), TRUE);
+  else
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.pframe_search_4), FALSE);
+  if (x264_gtk->inter_search_8)
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.inter_search_8), TRUE);
+  else
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.inter_search_8), FALSE);
+  if (x264_gtk->inter_search_4)
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.inter_search_4), TRUE);
+  else
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.partitions.inter_search_4), FALSE);
+
+  if (x264_gtk->use_as_reference)
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.bframes.use_as_reference), TRUE);
+  else
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.bframes.use_as_reference), FALSE);
+  if (x264_gtk->bidir_me)
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.bframes.bidir_me), TRUE);
+  else
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.bframes.bidir_me), FALSE);
+  if (x264_gtk->adaptive)
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.bframes.adaptive), TRUE);
+  else
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.bframes.adaptive), FALSE);
+  if (x264_gtk->weighted_biprediction)
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.bframes.weighted_biprediction), TRUE);
+  else
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->mb.bframes.weighted_biprediction), FALSE);
+  g_snprintf (buf, 5, "%d", x264_gtk->max_consecutive);
+  gtk_entry_set_text (GTK_ENTRY (config->mb.bframes.max_consecutive), buf);
+  gtk_range_set_value (GTK_RANGE (config->mb.bframes.bias), (gdouble)x264_gtk->bias);
+  gtk_combo_box_set_active (GTK_COMBO_BOX (config->mb.bframes.direct_mode), x264_gtk->direct_mode);
+
+  /* more */
+  if (x264_gtk->bframe_rdo)
+    gtk_combo_box_set_active (GTK_COMBO_BOX (config->more.motion_estimation.partition_decision), X264_PD_6b);
+  else
+    gtk_combo_box_set_active (GTK_COMBO_BOX (config->more.motion_estimation.partition_decision), x264_gtk->partition_decision);
+  gtk_combo_box_set_active (GTK_COMBO_BOX (config->more.motion_estimation.method), x264_gtk->me_method);
+  g_snprintf (buf, 5, "%d", x264_gtk->range);
+  gtk_entry_set_text (GTK_ENTRY (config->more.motion_estimation.range), buf);
+  if (x264_gtk->chroma_me)
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->more.motion_estimation.chroma_me), TRUE);
+  else
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->more.motion_estimation.chroma_me), FALSE);
+  g_snprintf (buf, 5, "%d", x264_gtk->max_ref_frames);
+  gtk_entry_set_text (GTK_ENTRY (config->more.motion_estimation.max_ref_frames), buf);
+  if (x264_gtk->mixed_refs)
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->more.motion_estimation.mixed_refs), TRUE);
+  else
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->more.motion_estimation.mixed_refs), FALSE);
+
+  g_snprintf (buf, 5, "%d", x264_gtk->sample_ar_x);
+  gtk_entry_set_text (GTK_ENTRY (config->more.misc.sample_ar_x), buf);
+  g_snprintf (buf, 5, "%d", x264_gtk->sample_ar_y);
+  gtk_entry_set_text (GTK_ENTRY (config->more.misc.sample_ar_y), buf);
+  g_snprintf (buf, 5, "%d", x264_gtk->threads);
+  gtk_entry_set_text (GTK_ENTRY (config->more.misc.threads), buf);
+  if (x264_gtk->cabac)
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->more.misc.cabac), TRUE);
+  else
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->more.misc.cabac), FALSE);
+  gtk_combo_box_set_active (GTK_COMBO_BOX (config->more.misc.trellis), x264_gtk->trellis);
+  g_snprintf (buf, 64, "%d", x264_gtk->noise_reduction);
+  gtk_entry_set_text (GTK_ENTRY (config->more.misc.noise_reduction), buf);
+  if (x264_gtk->deblocking_filter)
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->more.misc.df.deblocking_filter), TRUE);
+  else
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (config->more.misc.df.deblocking_filter), FALSE);
+  gtk_range_set_value (GTK_RANGE (config->more.misc.df.strength), (gdouble)x264_gtk->strength);
+  gtk_range_set_value (GTK_RANGE (config->more.misc.df.threshold), (gdouble)x264_gtk->threshold);
+
+  gtk_combo_box_set_active (GTK_COMBO_BOX (config->more.debug.log_level), x264_gtk->debug_method);
+  gtk_entry_set_text (GTK_ENTRY (config->more.debug.fourcc),
+  x264_gtk->fourcc);
+}
+
+static void
+_current_get (X264_Gui_Config *gconfig, X264_Gtk *x264_gtk)
+{
+  const gchar *text;
+
+  if (!gconfig)
+    return;
+
+  if (!x264_gtk)
+    g_print ("problem...\n");
+
+  /* bitrate */
+  switch (gtk_combo_box_get_active (GTK_COMBO_BOX (gconfig->bitrate.pass)))
+  {
+  case 0:
+    x264_gtk->pass = X264_PASS_SINGLE_BITRATE;
+    text = gtk_entry_get_text (GTK_ENTRY (gconfig->bitrate.w_average_bitrate));
+    x264_gtk->average_bitrate = (gint)g_ascii_strtoull (text, NULL, 10);
+    break;
+  case 1:
+    x264_gtk->pass = X264_PASS_SINGLE_QUANTIZER;
+    x264_gtk->quantizer = (gint)gtk_range_get_value (GTK_RANGE (gconfig->bitrate.w_quantizer));
+    break;
+  case 2:
+    x264_gtk->pass = X264_PASS_MULTIPASS_1ST;
+    text = gtk_entry_get_text (GTK_ENTRY (gconfig->bitrate.w_target_bitrate));
+    x264_gtk->target_bitrate = (gint)g_ascii_strtoull (text, NULL, 10);
+    break;
+  case 3:
+    x264_gtk->pass = X264_PASS_MULTIPASS_1ST_FAST;
+    text = gtk_entry_get_text (GTK_ENTRY (gconfig->bitrate.w_target_bitrate));
+    x264_gtk->target_bitrate = (gint)g_ascii_strtoull (text, NULL, 10);
+    break;
+  case 4:
+  default:
+    x264_gtk->pass = X264_PASS_MULTIPASS_NTH;
+    text = gtk_entry_get_text (GTK_ENTRY (gconfig->bitrate.w_target_bitrate));
+    x264_gtk->target_bitrate = (gint)g_ascii_strtoull (text, NULL, 10);
+    break;
+  }
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->bitrate.update_statfile)))
+    x264_gtk->update_statfile = 1;
+  else
+    x264_gtk->update_statfile = 0;
+
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->bitrate.statsfile_name));
+  memcpy (x264_gtk->statsfile_name,
+          text,
+          strlen(text) + 1);
+
+  /* rate control */
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->rate_control.bitrate.keyframe_boost));
+  x264_gtk->keyframe_boost = (gint)g_ascii_strtoull (text, NULL, 10);
+
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->rate_control.bitrate.bframes_reduction));
+  x264_gtk->bframes_reduction = (gint)g_ascii_strtoull (text, NULL, 10);
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->rate_control.bitrate.bitrate_variability));
+  x264_gtk->bitrate_variability = (gint)g_ascii_strtoull (text, NULL, 10);
+
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->rate_control.quantization_limits.min_qp));
+  x264_gtk->min_qp = (gint)g_ascii_strtoull (text, NULL, 10);
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->rate_control.quantization_limits.max_qp));
+  x264_gtk->max_qp = (gint)g_ascii_strtoull (text, NULL, 10);
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->rate_control.quantization_limits.max_qp_step));
+  x264_gtk->max_qp_step = (gint)g_ascii_strtoull (text, NULL, 10);
+
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->rate_control.scene_cuts.scene_cut_threshold));
+  x264_gtk->scene_cut_threshold = (gint)g_ascii_strtoull (text, NULL, 10);
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->rate_control.scene_cuts.min_idr_frame_interval));
+  x264_gtk->min_idr_frame_interval = (gint)g_ascii_strtoull (text, NULL, 10);
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->rate_control.scene_cuts.max_idr_frame_interval));
+  x264_gtk->max_idr_frame_interval = (gint)g_ascii_strtoull (text, NULL, 10);
+
+  /* mb */
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->mb.partitions.transform_8x8)))
+    x264_gtk->transform_8x8 = 1;
+  else
+    x264_gtk->transform_8x8 = 0;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->mb.partitions.pframe_search_8)))
+    x264_gtk->pframe_search_8 = 1;
+  else
+    x264_gtk->pframe_search_8 = 0;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->mb.partitions.bframe_search_8)))
+    x264_gtk->bframe_search_8 = 1;
+  else
+    x264_gtk->bframe_search_8 = 0;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->mb.partitions.pframe_search_4)))
+    x264_gtk->pframe_search_4 = 1;
+  else
+    x264_gtk->pframe_search_4 = 0;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->mb.partitions.inter_search_8)))
+    x264_gtk->inter_search_8 = 1;
+  else
+    x264_gtk->inter_search_8 = 0;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->mb.partitions.inter_search_4)))
+    x264_gtk->inter_search_4 = 1;
+  else
+    x264_gtk->inter_search_4 = 0;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->mb.bframes.use_as_reference)))
+    x264_gtk->use_as_reference = 1;
+  else
+    x264_gtk->use_as_reference = 0;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->mb.bframes.bidir_me)))
+    x264_gtk->bidir_me = 1;
+  else
+    x264_gtk->bidir_me = 0;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->mb.bframes.adaptive)))
+    x264_gtk->adaptive = 1;
+  else
+    x264_gtk->adaptive = 0;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->mb.bframes.weighted_biprediction)))
+    x264_gtk->weighted_biprediction = 1;
+  else
+    x264_gtk->weighted_biprediction = 0;
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->mb.bframes.max_consecutive));
+  x264_gtk->max_consecutive = (gint)g_ascii_strtoull (text, NULL, 10);
+  x264_gtk->bias = (gint)gtk_range_get_value (GTK_RANGE (gconfig->mb.bframes.bias));
+
+  switch (gtk_combo_box_get_active (GTK_COMBO_BOX (gconfig->mb.bframes.direct_mode)))
+    {
+    case 0:
+      x264_gtk->direct_mode = X264_NONE;
+    case 1:
+      x264_gtk->direct_mode = X264_SPATIAL;
+      break;
+    default:
+      x264_gtk->direct_mode = X264_TEMPORAL;
+      break;
+    }
+
+  /* more */
+  switch (gtk_combo_box_get_active (GTK_COMBO_BOX (gconfig->more.motion_estimation.partition_decision)))
+    {
+    case 0:
+      x264_gtk->partition_decision = X264_PD_1;
+      break;
+    case 1:
+      x264_gtk->partition_decision = X264_PD_2;
+      break;
+    case 2:
+      x264_gtk->partition_decision = X264_PD_3;
+      break;
+    case 3:
+      x264_gtk->partition_decision = X264_PD_4;
+      break;
+    case 4:
+      x264_gtk->partition_decision = X264_PD_5;
+      break;
+    case 5:
+      x264_gtk->partition_decision = X264_PD_6;
+      break;
+    default:
+      x264_gtk->partition_decision = X264_PD_6;
+      x264_gtk->bframe_rdo = 1;
+      break;
+    }
+  switch (gtk_combo_box_get_active (GTK_COMBO_BOX (gconfig->more.motion_estimation.method)))
+    {
+    case 0:
+      x264_gtk->me_method = X264_ME_METHOD_DIAMOND;
+      break;
+    case 1:
+      x264_gtk->me_method = X264_ME_METHOD_HEXAGONAL;
+      break;
+    case 2:
+      x264_gtk->me_method = X264_ME_METHOD_UNEVEN_MULTIHEXA;
+      break;
+    default:
+      x264_gtk->me_method = X264_ME_METHOD_EXHAUSTIVE;
+      break;
+    }
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->more.motion_estimation.range));
+  x264_gtk->range = (gint)g_ascii_strtoull (text, NULL, 10);
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->more.motion_estimation.chroma_me)))
+    x264_gtk->chroma_me = 1;
+  else
+    x264_gtk->chroma_me = 0;
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->more.motion_estimation.max_ref_frames));
+  x264_gtk->max_ref_frames = (gint)g_ascii_strtoull (text, NULL, 10);
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->more.motion_estimation.mixed_refs)))
+    x264_gtk->mixed_refs = 1;
+  else
+    x264_gtk->mixed_refs = 0;
+
+
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->more.misc.sample_ar_x));
+  x264_gtk->sample_ar_x = (gint)g_ascii_strtoull (text, NULL, 10);
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->more.misc.sample_ar_y));
+  x264_gtk->sample_ar_y = (gint)g_ascii_strtoull (text, NULL, 10);
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->more.misc.threads));
+  x264_gtk->threads = (gint)g_ascii_strtoull (text, NULL, 10);
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->more.misc.cabac)))
+    x264_gtk->cabac = 1;
+  else
+    x264_gtk->cabac = 0;
+  x264_gtk->trellis = gtk_combo_box_get_active (GTK_COMBO_BOX (gconfig->more.misc.trellis));
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->more.misc.noise_reduction));
+  x264_gtk->noise_reduction = (gint)g_ascii_strtoull (text, NULL, 10);
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->more.misc.df.deblocking_filter)))
+    x264_gtk->deblocking_filter = 1;
+  else
+    x264_gtk->deblocking_filter = 0;
+  x264_gtk->strength = (gint)gtk_range_get_value (GTK_RANGE (gconfig->more.misc.df.strength));
+  x264_gtk->threshold = (gint)gtk_range_get_value (GTK_RANGE (gconfig->more.misc.df.threshold));
+
+  switch (gtk_combo_box_get_active (GTK_COMBO_BOX (gconfig->more.debug.log_level)))
+    {
+    case 0:
+      x264_gtk->debug_method = X264_DEBUG_METHOD_NONE;
+      break;
+    case 1:
+      x264_gtk->debug_method = X264_DEBUG_METHOD_ERROR;
+      break;
+    case 2:
+      x264_gtk->debug_method = X264_DEBUG_METHOD_WARNING;
+      break;
+    case 3:
+      x264_gtk->debug_method = X264_DEBUG_METHOD_INFO;
+      break;
+    default:
+      x264_gtk->debug_method = X264_DEBUG_METHOD_DEBUG;
+      break;
+    }
+  text = gtk_entry_get_text (GTK_ENTRY (gconfig->more.debug.fourcc));
+  memcpy (x264_gtk->fourcc, text, strlen (text) + 1);
+}
diff --git a/gtk/x264_gtk.h b/gtk/x264_gtk.h
new file mode 100644 (file)
index 0000000..cb552d1
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef __X264_GTK_H__
+#define __X264_GTK_H__
+
+
+#include "x264_gtk_enum.h"
+
+
+typedef struct X264_Gtk_ X264_Gtk;
+
+struct X264_Gtk_
+{
+  /* video properties */
+  gint width;
+  gint height;
+  gint csp;
+
+  /* bitrate */
+  X264_Pass pass;
+  gint average_bitrate;
+  gint target_bitrate;
+  gint quantizer;
+  gint desired_size;
+  gint statfile_length; /* length of the filename (as returned by strlen) */
+  gchar statsfile_name[4095+1];
+
+  /* rc */
+  gint keyframe_boost;
+  gint bframes_reduction;
+  gint bitrate_variability;
+
+  gint min_qp;
+  gint max_qp;
+  gint max_qp_step;
+
+  gint scene_cut_threshold;
+  gint min_idr_frame_interval;
+  gint max_idr_frame_interval;
+
+  /* mb */
+
+  gint max_consecutive;
+  gint bias;
+  X264_Direct_Mode direct_mode;
+
+  /* more */
+  X264_Partition_Decision partition_decision;
+  X264_Me_Method me_method;
+  gint range;
+  gint max_ref_frames;
+
+  gint sample_ar_x;
+  gint sample_ar_y;
+  gint threads;
+  guint trellis;
+  gint noise_reduction;
+  
+  gint strength;
+  gint threshold;
+
+  X264_Debug_Method debug_method;
+  gchar fourcc[4+1];
+
+  /* bitrate */
+  guint update_statfile       : 1;
+  /* mb - partitions */
+  guint transform_8x8         : 1;
+  guint pframe_search_8       : 1;
+  guint bframe_search_8       : 1;
+  guint pframe_search_4       : 1;
+  guint inter_search_8        : 1;
+  guint inter_search_4        : 1;
+  /* mb - bframes */
+  guint use_as_reference      : 1;
+  guint bidir_me                  : 1;
+  guint adaptive              : 1;
+  guint weighted_biprediction : 1;
+  /* more - me */
+  guint bframe_rdo            : 1;
+  guint chroma_me             : 1;
+  guint mixed_refs            : 1;
+  /* more - misc */
+  guint cabac                 : 1;
+  /* more - misc - df */
+  guint deblocking_filter     : 1;
+};
+
+x264_param_t *x264_gtk_param_get (X264_Gtk *x264_gtk);
+X264_Gtk     *x264_gtk_load (void);
+GtkWidget    *x264_gtk_window_create (GtkWidget *parent);
+void          x264_gtk_shutdown (GtkWidget *dialog);
+
+
+#endif /* __X264_GTK_H__ */
diff --git a/gtk/x264_gtk_bitrate.c b/gtk/x264_gtk_bitrate.c
new file mode 100644 (file)
index 0000000..aba460f
--- /dev/null
@@ -0,0 +1,187 @@
+#if defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ || defined __DragonFly__
+#  include <inttypes.h>
+#else
+#  include <stdint.h>
+#endif
+
+#include <gtk/gtk.h>
+
+#include "../x264.h"
+#include "x264_gtk_private.h"
+#include "x264_gtk_enum.h"
+#include "x264_gtk_bitrate.h"
+
+
+/* Callbacks */
+static void     _bitrate_pass     (GtkComboBox     *combo,
+                                   gpointer         user_data);
+static void     _bitrate_statfile (GtkToggleButton *button,
+                                   gpointer         user_data);
+
+GtkWidget *
+_bitrate_page (X264_Gui_Config *gconfig)
+{
+  GtkWidget         *vbox;
+  GtkWidget         *frame;
+  GtkWidget         *table;
+  GtkWidget         *image;
+  GtkWidget         *label;
+
+  vbox = gtk_vbox_new (FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
+
+  image = gtk_image_new_from_file (X264_DATA_DIR "/x264.png");
+  gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, TRUE, 6);
+  gtk_widget_show (image);
+
+  frame = gtk_frame_new ("Main settings");
+  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 6);
+  gtk_widget_show (frame);
+
+  table = gtk_table_new (2, 2, TRUE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
+  gtk_container_set_border_width (GTK_CONTAINER (table), 6);
+  gtk_container_add (GTK_CONTAINER (frame), table);
+  gtk_widget_show (table);
+
+  label = gtk_label_new ("Encoding type");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 0, 1);
+  gtk_widget_show (label);
+
+  gconfig->bitrate.pass = gtk_combo_box_new_text ();
+  gtk_combo_box_append_text (GTK_COMBO_BOX (gconfig->bitrate.pass),
+                             "Single Pass - Bitrate");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (gconfig->bitrate.pass),
+                             "Single Pass - Quantizer");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (gconfig->bitrate.pass),
+                             "Multipass - First Pass");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (gconfig->bitrate.pass),
+                             "Multipass - First Pass (fast)");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (gconfig->bitrate.pass),
+                             "Multipass - Nth Pass");
+  gtk_table_attach_defaults (GTK_TABLE (table), gconfig->bitrate.pass,
+                             1, 2, 0, 1);
+  g_signal_connect (G_OBJECT (gconfig->bitrate.pass),
+                    "changed",
+                    G_CALLBACK (_bitrate_pass),
+                    gconfig);
+  gtk_widget_show (gconfig->bitrate.pass);
+
+  gconfig->bitrate.label = gtk_label_new ("Quantizer");
+  gtk_misc_set_alignment (GTK_MISC (gconfig->bitrate.label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), gconfig->bitrate.label,
+                             0, 1, 1, 2);
+  gtk_widget_show (gconfig->bitrate.label);
+
+  gconfig->bitrate.w_quantizer = gtk_hscale_new_with_range (0.0, 51.0, 1.0);
+  gtk_scale_set_digits (GTK_SCALE (gconfig->bitrate.w_quantizer), 0);
+  gtk_scale_set_value_pos (GTK_SCALE (gconfig->bitrate.w_quantizer), GTK_POS_RIGHT);
+  gtk_table_attach_defaults (GTK_TABLE (table), gconfig->bitrate.w_quantizer,
+                             1, 2, 1, 2);
+
+  gconfig->bitrate.w_average_bitrate = gtk_entry_new_with_max_length (4095);
+  gtk_table_attach_defaults (GTK_TABLE (table), gconfig->bitrate.w_average_bitrate,
+                             1, 2, 1, 2);
+
+  gconfig->bitrate.w_target_bitrate = gtk_entry_new_with_max_length (4095);
+  gtk_table_attach_defaults (GTK_TABLE (table), gconfig->bitrate.w_target_bitrate,
+                             1, 2, 1, 2);
+
+  frame = gtk_frame_new ("Statistic file");
+  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 6);
+  gtk_widget_show (frame);
+
+  table = gtk_table_new (2, 2, TRUE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
+  gtk_container_set_border_width (GTK_CONTAINER (table), 6);
+  gtk_container_add (GTK_CONTAINER (frame), table);
+  gtk_widget_show (table);
+
+  gconfig->bitrate.update_statfile = gtk_check_button_new_with_label ("Update Statfile");
+  g_signal_connect (G_OBJECT (gconfig->bitrate.update_statfile),
+                    "toggled",
+                    G_CALLBACK (_bitrate_statfile), gconfig);
+  gtk_table_attach_defaults (GTK_TABLE (table), gconfig->bitrate.update_statfile,
+                             0, 1, 0, 1);
+  gtk_widget_show (gconfig->bitrate.update_statfile);
+
+  label = gtk_label_new ("Statsfile name");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 1, 2);
+  gtk_widget_show (label);
+
+  gconfig->bitrate.statsfile_name = gtk_entry_new_with_max_length (4095);
+  gtk_table_attach_defaults (GTK_TABLE (table), gconfig->bitrate.statsfile_name,
+                             1, 2, 1, 2);
+  gtk_widget_show (gconfig->bitrate.statsfile_name);
+
+  return vbox;
+}
+
+/* Callbacks */
+static void
+_bitrate_pass (GtkComboBox *combo,
+               gpointer    user_data)
+{
+  X264_Gui_Config *gconfig;
+
+  gconfig = (X264_Gui_Config *)user_data;
+
+  switch (gtk_combo_box_get_active (combo))
+    {
+    case X264_PASS_SINGLE_BITRATE:
+      gtk_label_set_text (GTK_LABEL (gconfig->bitrate.label), "Average bitrate");
+      if (!GTK_WIDGET_VISIBLE (gconfig->bitrate.w_average_bitrate)) {
+        gtk_widget_hide (gconfig->bitrate.w_quantizer);
+        gtk_widget_hide (gconfig->bitrate.w_target_bitrate);
+        gtk_widget_show (gconfig->bitrate.w_average_bitrate);
+      }
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gconfig->bitrate.update_statfile), FALSE);
+      break;
+    case X264_PASS_SINGLE_QUANTIZER:
+      gtk_label_set_text (GTK_LABEL (gconfig->bitrate.label), "Quantizer");
+      if (!GTK_WIDGET_VISIBLE (gconfig->bitrate.w_quantizer)) {
+        gtk_widget_hide (gconfig->bitrate.w_average_bitrate);
+        gtk_widget_hide (gconfig->bitrate.w_target_bitrate);
+        gtk_widget_show (gconfig->bitrate.w_quantizer);
+      }
+      break;
+    case X264_PASS_MULTIPASS_1ST:
+    case X264_PASS_MULTIPASS_1ST_FAST:
+      gtk_label_set_text (GTK_LABEL (gconfig->bitrate.label), "Target bitrate");
+      if (!GTK_WIDGET_VISIBLE (gconfig->bitrate.w_target_bitrate)) {
+        gtk_widget_hide (gconfig->bitrate.w_quantizer);
+        gtk_widget_hide (gconfig->bitrate.w_average_bitrate);
+        gtk_widget_show (gconfig->bitrate.w_target_bitrate);
+      }
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gconfig->bitrate.update_statfile), TRUE);
+      break;
+    case X264_PASS_MULTIPASS_NTH:
+      gtk_label_set_text (GTK_LABEL (gconfig->bitrate.label), "Target bitrate");
+      if (!GTK_WIDGET_VISIBLE (gconfig->bitrate.w_target_bitrate)) {
+        gtk_widget_hide (gconfig->bitrate.w_quantizer);
+        gtk_widget_hide (gconfig->bitrate.w_average_bitrate);
+        gtk_widget_show (gconfig->bitrate.w_target_bitrate);
+      }
+      break;
+    }
+}
+
+static void
+_bitrate_statfile (GtkToggleButton *button,
+                   gpointer         user_data)
+{
+  X264_Gui_Config *gconfig;
+
+  gconfig = (X264_Gui_Config *)user_data;
+
+  if (gtk_toggle_button_get_active (button))
+    gtk_widget_set_sensitive (gconfig->bitrate.statsfile_name, TRUE);
+  else
+    gtk_widget_set_sensitive (gconfig->bitrate.statsfile_name, FALSE);
+}
diff --git a/gtk/x264_gtk_bitrate.h b/gtk/x264_gtk_bitrate.h
new file mode 100644 (file)
index 0000000..f44937b
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __X264_GTK_BITRATE_H__
+#define __X264_GTK_BITRATE_H__
+
+
+GtkWidget *_bitrate_page (X264_Gui_Config *config);
+
+
+#endif /* __X264_GTK_BITRATE_H__ */
diff --git a/gtk/x264_gtk_encode.c b/gtk/x264_gtk_encode.c
new file mode 100644 (file)
index 0000000..55ac7f7
--- /dev/null
@@ -0,0 +1,16 @@
+#include <gtk/gtk.h>
+
+#include "x264_gtk_encode_main_window.h"
+
+int
+main (int argc, char *argv[])
+{
+  g_thread_init (NULL);
+  gtk_init (&argc, &argv);
+
+  x264_gtk_encode_main_window ();
+
+  gtk_main ();
+
+  return 0;
+}
diff --git a/gtk/x264_gtk_encode_encode.c b/gtk/x264_gtk_encode_encode.c
new file mode 100644 (file)
index 0000000..663cb81
--- /dev/null
@@ -0,0 +1,250 @@
+#include <string.h>
+#if defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ || defined __DragonFly__
+#  include <inttypes.h>
+#else
+#  include <stdint.h>
+#endif
+
+#include <gtk/gtk.h>
+
+#include "../x264.h"
+#include "../muxers.h"
+#include "x264_gtk_encode_private.h"
+
+
+#define DATA_MAX 3000000
+uint8_t data[DATA_MAX];
+
+int64_t x264_mdate (void);
+
+/* input interface */
+int (*p_open_infile)( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param );
+int (*p_get_frame_total)( hnd_t handle );
+int (*p_read_frame)( x264_picture_t *p_pic, hnd_t handle, int i_frame );
+int (*p_close_infile)( hnd_t handle );
+
+/* output interface */
+static int (*p_open_outfile)      (char *filename, void **handle);
+static int (*p_set_outfile_param) (void *handle, x264_param_t *p_param);
+static int (*p_write_nalu)        (void *handle, uint8_t *p_nal, int i_size);
+static int (*p_set_eop)           (void *handle, x264_picture_t *p_picture);
+static int (*p_close_outfile)     (void *handle);
+
+
+
+static void _set_drivers  (int container);
+static int  _encode_frame (x264_t *h, void *handle, x264_picture_t *pic);
+
+
+gpointer
+x264_gtk_encode_encode (X264_Thread_Data *thread_data)
+{
+  GIOStatus       status;
+  gsize           size;
+  X264_Pipe_Data  pipe_data;
+  x264_param_t   *param;
+  x264_picture_t  pic;
+  x264_t         *h;
+  hnd_t           hin;
+  hnd_t           hout;
+  int             i_frame;
+  int             i_frame_total;
+  int64_t         i_start;
+  int64_t         i_end;
+  int64_t         i_file;
+  int             i_frame_size;
+  int             i_progress;
+
+  g_print ("encoding...\n");
+  param = thread_data->param;
+  _set_drivers (thread_data->container);
+
+  if (p_open_infile (thread_data->file_input, &hin, param)) {
+    fprintf( stderr, "could not open input file '%s'\n", thread_data->file_input );
+    return NULL;
+  }
+
+  p_open_outfile ((char *)thread_data->file_output, &hout);
+
+  i_frame_total = p_get_frame_total (hin );
+  if (((i_frame_total == 0) || (param->i_frame_total < i_frame_total)) &&
+      (param->i_frame_total > 0))
+    i_frame_total = param->i_frame_total;
+  param->i_frame_total = i_frame_total;
+
+  if ((h = x264_encoder_open (param)) == NULL)
+    {
+      fprintf (stderr, "x264_encoder_open failed\n");
+      p_close_infile (hin);
+      p_close_outfile (hout);
+      g_free (param);
+
+      return NULL;
+    }
+
+  if (p_set_outfile_param (hout, param))
+    {
+      fprintf (stderr, "can't set outfile param\n");
+      p_close_infile (hin);
+      p_close_outfile (hout);
+      g_free (param);
+
+      return NULL;
+    }
+
+  /* Create a new pic */
+  x264_picture_alloc (&pic, X264_CSP_I420, param->i_width, param->i_height );
+
+  i_start = x264_mdate();
+
+  /* Encode frames */
+  for (i_frame = 0, i_file = 0, i_progress = 0;
+       ((i_frame < i_frame_total) || (i_frame_total == 0)); )
+    {
+      if (p_read_frame (&pic, hin, i_frame))
+        break;
+
+      pic.i_pts = (int64_t)i_frame * param->i_fps_den;
+
+      i_file += _encode_frame (h, hout, &pic);
+
+      i_frame++;
+
+      /* update status line (up to 1000 times per input file) */
+      if (param->i_log_level < X264_LOG_DEBUG && 
+          (i_frame_total ? i_frame * 1000 / i_frame_total > i_progress
+           : i_frame % 10 == 0))
+        {
+          int64_t i_elapsed = x264_mdate () - i_start;
+          double fps = i_elapsed > 0 ? i_frame * 1000000. / i_elapsed : 0;
+
+          if (i_frame_total)
+            {
+              pipe_data.frame = i_frame;
+              pipe_data.frame_total = i_frame_total;
+              pipe_data.file = i_file;
+              pipe_data.elapsed = i_elapsed;
+              status = g_io_channel_write_chars (thread_data->io_write,
+                                                 (const gchar *)&pipe_data,
+                                                 sizeof (X264_Pipe_Data),
+                                                 &size, NULL);
+              if (status != G_IO_STATUS_NORMAL) {
+                g_print ("Error ! %d %d %d\n", status, sizeof (X264_Pipe_Data), size);
+              }
+              else {
+                /* we force the GIOChannel to write to the pipeline */
+                status = g_io_channel_flush (thread_data->io_write,
+                                             NULL);
+                if (status != G_IO_STATUS_NORMAL) {
+                  g_print ("Error ! %d\n", status);
+                }
+              }
+            }
+          else
+            fprintf( stderr, "encoded frames: %d, %.2f fps   \r", i_frame, fps );
+          fflush( stderr ); /* needed in windows */
+        }
+    }
+  /* Flush delayed B-frames */
+  do {
+    i_file += i_frame_size = _encode_frame (h, hout, NULL);
+  } while (i_frame_size);
+
+  i_end = x264_mdate ();
+  x264_picture_clean (&pic);
+  x264_encoder_close (h);
+  fprintf (stderr, "\n");
+
+  p_close_infile (hin);
+  p_close_outfile (hout);
+
+  if (i_frame > 0) {
+    double fps = (double)i_frame * (double)1000000 /
+      (double)(i_end - i_start);
+
+    fprintf (stderr, "encoded %d frames, %.2f fps, %.2f kb/s\n",
+             i_frame, fps,
+             (double) i_file * 8 * param->i_fps_num /
+             ((double) param->i_fps_den * i_frame * 1000));
+  }
+  return NULL;
+}
+
+static void
+_set_drivers (gint container)
+{
+/*   Default input file driver */
+  p_open_infile = open_file_yuv;
+  p_get_frame_total = get_frame_total_yuv;
+  p_read_frame = read_frame_yuv;
+  p_close_infile = close_file_yuv;
+
+  switch (container) {
+  case 0:
+/*     Raw ES output file driver */
+    p_open_outfile = open_file_bsf;
+    p_set_outfile_param = set_param_bsf;
+    p_write_nalu = write_nalu_bsf;
+    p_set_eop = set_eop_bsf;
+    p_close_outfile = close_file_bsf;
+    break;
+  case 1:
+/*     Matroska output file driver */
+    p_open_outfile = open_file_mkv;
+    p_set_outfile_param = set_param_mkv;
+    p_write_nalu = write_nalu_mkv;
+    p_set_eop = set_eop_mkv;
+    p_close_outfile = close_file_mkv;
+    break;
+#ifdef MP4_OUTPUT
+  case 2:
+    p_open_outfile = open_file_mp4;
+    p_set_outfile_param = set_param_mp4;
+    p_write_nalu = write_nalu_mp4;
+    p_set_eop = set_eop_mp4;
+    p_close_outfile = close_file_mp4;
+    break;
+#endif
+  }
+}
+
+static int
+_encode_frame (x264_t *h, void *handle, x264_picture_t *pic)
+{
+  x264_picture_t pic_out;
+  x264_nal_t    *nal;
+  int            i_nal;
+  int            i;
+  int            i_file = 0;
+
+  /* Do not force any parameters */
+  if (pic)
+    {
+      pic->i_type = X264_TYPE_AUTO;
+      pic->i_qpplus1 = 0;
+    }
+  if (x264_encoder_encode (h, &nal, &i_nal, pic, &pic_out) < 0)
+    {
+      fprintf (stderr, "x264_encoder_encode failed\n");
+    }
+
+  for (i = 0; i < i_nal; i++)
+    {
+      int i_size;
+      int i_data;
+
+      i_data = DATA_MAX;
+      if ((i_size = x264_nal_encode (data, &i_data, 1, &nal[i])) > 0 )
+        {
+          i_file += p_write_nalu (handle, data, i_size);
+        }
+      else if (i_size < 0)
+        {
+          fprintf (stderr, "need to increase buffer size (size=%d)\n", -i_size);
+        }
+    }
+  if (i_nal)
+    p_set_eop (handle, &pic_out);
+
+  return i_file;
+}
diff --git a/gtk/x264_gtk_encode_encode.h b/gtk/x264_gtk_encode_encode.h
new file mode 100644 (file)
index 0000000..e075480
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __X264_GTK_ENCODE_ENCODE_H__
+#define __X264_GTK_ENCODE_ENCODE_H__
+
+
+gpointer x264_gtk_encode_encode (X264_Thread_Data *thread_data);
+
+
+#endif /* __X264_GTK_ENCODE_ENCODE_H__ */
diff --git a/gtk/x264_gtk_encode_main_window.c b/gtk/x264_gtk_encode_main_window.c
new file mode 100644 (file)
index 0000000..07bee21
--- /dev/null
@@ -0,0 +1,461 @@
+#if defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ || defined __DragonFly__
+#  include <inttypes.h>
+#else
+#  include <stdint.h>
+#endif
+#include <unistd.h>
+
+#include <gtk/gtk.h>
+
+#include "../x264.h"
+#include "x264_gtk.h"
+#include "x264_gtk_encode_private.h"
+#include "x264_gtk_encode_encode.h"
+#include "x264_gtk_encode_status_window.h"
+
+
+typedef struct X264_Gtk_Encode_ X264_Gtk_Encode;
+
+struct X264_Gtk_Encode_
+{
+  GtkWidget *main_dialog;
+
+  /* input */
+  GtkWidget *file_input;
+  GtkWidget *width;
+  GtkWidget *height;
+  GtkWidget *fps_num;
+  GtkWidget *fps_den;
+  GtkWidget *frame_count;
+  
+  /* output */
+  GtkWidget *path_output;
+  GtkWidget *file_output;
+  GtkWidget *combo;
+};
+
+
+/* Callbacks */
+static gboolean _delete_window_cb    (GtkWidget *widget,
+                                      GdkEvent  *event,
+                                      gpointer   user_data);
+static void     _configure_window_cb (GtkButton *button,
+                                      gpointer   user_data);
+static void     _response_window_cb  (GtkDialog *dialog,
+                                      gint       res,
+                                      gpointer   user_data);
+
+
+static gboolean _fill_status_window (GIOChannel  *io,
+                                     GIOCondition condition,
+                                     gpointer     user_data);
+/* Code */
+
+void
+x264_gtk_encode_main_window ()
+{
+  GtkWidget       *dialog;
+  GtkWidget       *frame;
+  GtkWidget       *button;
+  GtkWidget       *table;
+  GtkWidget       *label;
+  GtkFileFilter   *filter;
+  X264_Gtk_Encode *encode;
+
+  encode = (X264_Gtk_Encode *)g_malloc0 (sizeof (X264_Gtk_Encode));
+
+  dialog = gtk_dialog_new_with_buttons ("X264 Gtk Encoder",
+                                        NULL, 0,
+                                        NULL);
+  g_signal_connect (G_OBJECT (dialog),
+                    "delete-event",
+                    G_CALLBACK (_delete_window_cb),
+                    encode);
+  g_signal_connect (G_OBJECT (dialog),
+                    "response",
+                    G_CALLBACK (_response_window_cb),
+                    encode);
+  encode->main_dialog = dialog;
+
+  button = gtk_button_new_with_label ("Configure");
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), button, FALSE, TRUE, 6);
+  g_signal_connect (G_OBJECT (button),
+                    "clicked",
+                    G_CALLBACK (_configure_window_cb),
+                    dialog);
+  gtk_widget_show (button);
+
+  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+                          GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
+                          GTK_STOCK_EXECUTE, GTK_RESPONSE_APPLY,
+                          NULL);
+
+  /* input */
+  frame = gtk_frame_new ("Input file");
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame, FALSE, TRUE, 6);
+  gtk_widget_show (frame);
+
+  table = gtk_table_new (6, 2, TRUE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
+  gtk_container_set_border_width (GTK_CONTAINER (table), 6);
+  gtk_container_add (GTK_CONTAINER (frame), table);
+  gtk_widget_show (table);
+
+  label = gtk_label_new ("Input file:");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
+  gtk_widget_show (label);
+
+  encode->file_input = gtk_file_chooser_button_new ("Select a file",
+                                                    GTK_FILE_CHOOSER_ACTION_OPEN);
+  gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (encode->file_input),
+                                       g_get_home_dir ());
+  filter = gtk_file_filter_new ();
+  gtk_file_filter_add_pattern (GTK_FILE_FILTER (filter), "*.yuv");
+  gtk_file_filter_add_pattern (GTK_FILE_FILTER (filter), "*.cif");
+  gtk_file_filter_add_pattern (GTK_FILE_FILTER (filter), "*.qcif");
+  gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (encode->file_input),
+                               filter);
+  gtk_table_attach_defaults (GTK_TABLE (table), encode->file_input, 1, 2, 0, 1);
+  gtk_widget_show (encode->file_input);
+
+  label = gtk_label_new ("Width:");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
+  gtk_widget_show (label);
+
+  encode->width = gtk_entry_new_with_max_length (4095);
+  gtk_entry_set_text (GTK_ENTRY (encode->width), "352");
+  gtk_table_attach_defaults (GTK_TABLE (table), encode->width, 1, 2, 1, 2);
+  gtk_widget_show (encode->width);
+
+  label = gtk_label_new ("Height:");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3);
+  gtk_widget_show (label);
+
+  encode->height = gtk_entry_new_with_max_length (4095);
+  gtk_entry_set_text (GTK_ENTRY (encode->height), "288");
+  gtk_table_attach_defaults (GTK_TABLE (table), encode->height, 1, 2, 2, 3);
+  gtk_widget_show (encode->height);
+
+  label = gtk_label_new ("Frame rate num:");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 3, 4);
+  gtk_widget_show (label);
+
+  encode->fps_num = gtk_entry_new_with_max_length (4095);
+  gtk_entry_set_text (GTK_ENTRY (encode->fps_num), "25");
+  gtk_table_attach_defaults (GTK_TABLE (table), encode->fps_num, 1, 2, 3, 4);
+  gtk_widget_show (encode->fps_num);
+
+  label = gtk_label_new ("Frame rate den:");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 4, 5);
+  gtk_widget_show (label);
+
+  encode->fps_den = gtk_entry_new_with_max_length (4095);
+  gtk_entry_set_text (GTK_ENTRY (encode->fps_den), "1");
+  gtk_table_attach_defaults (GTK_TABLE (table), encode->fps_den, 1, 2, 4, 5);
+  gtk_widget_show (encode->fps_den);
+
+  label = gtk_label_new ("Frame count:");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
+  gtk_widget_show (label);
+
+  encode->frame_count = gtk_entry_new_with_max_length (4095);
+  gtk_entry_set_text (GTK_ENTRY (encode->frame_count), "0");
+  gtk_table_attach_defaults (GTK_TABLE (table), encode->frame_count, 1, 2, 5, 6);
+  gtk_widget_show (encode->frame_count);
+
+  /* output */
+  frame = gtk_frame_new ("Output file");
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame, FALSE, TRUE, 6);
+  gtk_widget_show (frame);
+
+  table = gtk_table_new (3, 2, TRUE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
+  gtk_container_set_border_width (GTK_CONTAINER (table), 6);
+  gtk_container_add (GTK_CONTAINER (frame), table);
+  gtk_widget_show (table);
+
+  label = gtk_label_new ("Output path:");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
+  gtk_widget_show (label);
+
+  encode->path_output = gtk_file_chooser_button_new ("Select a path",
+                                                     GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+  gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (encode->path_output),
+                                       g_get_home_dir ());
+  gtk_table_attach_defaults (GTK_TABLE (table), encode->path_output, 1, 2, 0, 1);
+  gtk_widget_show (encode->path_output);
+
+  label = gtk_label_new ("Output file (without ext.):");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
+  gtk_widget_show (label);
+
+  encode->file_output = gtk_entry_new_with_max_length (4095);
+  gtk_table_attach_defaults (GTK_TABLE (table), encode->file_output, 1, 2, 1, 2);
+  gtk_widget_show (encode->file_output);
+
+  label = gtk_label_new ("Container:");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3);
+  gtk_widget_show (label);
+
+  encode->combo = gtk_combo_box_new_text ();
+  gtk_combo_box_append_text (GTK_COMBO_BOX (encode->combo),
+                             "Raw ES");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (encode->combo),
+                             "Matroska");
+#ifdef MP4_OUTPUT
+  gtk_combo_box_append_text (GTK_COMBO_BOX (encode->combo),
+                             "Mp4");
+#endif
+  gtk_table_attach_defaults (GTK_TABLE (table), encode->combo, 1, 2, 2, 3);
+  gtk_widget_show (encode->combo);
+
+  gtk_combo_box_set_active (GTK_COMBO_BOX (encode->combo), 0);
+
+  gtk_widget_show (dialog);
+}
+
+/* Callbacks */
+
+static void
+_encode_shutdown (X264_Gtk_Encode *encode)
+{
+  if (!encode) return;
+
+  g_free (encode);
+  encode = NULL;
+}
+
+static gboolean
+_delete_window_cb (GtkWidget *widget __UNUSED__,
+                   GdkEvent  *event __UNUSED__,
+                   gpointer   user_data)
+{
+  gtk_main_quit ();
+  _encode_shutdown ((X264_Gtk_Encode *)user_data);
+
+  return TRUE;
+}
+
+static void
+_configure_window_cb (GtkButton *button __UNUSED__,
+                      gpointer   user_data)
+{
+  GtkWidget *window;
+  
+  window = x264_gtk_window_create (GTK_WIDGET (user_data));
+  x264_gtk_shutdown (window);
+}
+
+static void
+_response_window_cb (GtkDialog *dialog,
+                     gint       res,
+                     gpointer   user_data)
+{
+  switch (res) {
+  case GTK_RESPONSE_APPLY: {
+    x264_param_t     *param;
+    X264_Gtk         *x264_gtk;
+    X264_Gtk_Encode  *encode;
+    X264_Thread_Data *thread_data;
+    GtkWidget        *win_status;
+    GThread          *thread;
+    const gchar      *file_input = NULL;
+    const gchar      *path_output = NULL;
+    const gchar      *filename_output = NULL;
+    gchar            *file_output = NULL;
+    gchar            *ext;
+    gint              fds[2];
+    gint              container;
+
+    encode = (X264_Gtk_Encode *)user_data;
+    file_input = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (encode->file_input));
+    path_output = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (encode->path_output));
+    filename_output = gtk_entry_get_text (GTK_ENTRY (encode->file_output));
+
+    if (!file_input || 
+        (file_input[0] == '\0')) {
+      GtkWidget *dialog_message;
+
+      dialog_message = gtk_message_dialog_new (GTK_WINDOW (dialog),
+                                       GTK_DIALOG_DESTROY_WITH_PARENT,
+                                       GTK_MESSAGE_ERROR,
+                                       GTK_BUTTONS_CLOSE,
+                                               "Error: input file name is not set");
+      gtk_dialog_run (GTK_DIALOG (dialog_message));
+      gtk_widget_destroy (dialog_message);
+      break;
+    }
+    
+    if (!filename_output || 
+        (filename_output[0] == '\0')) {
+      GtkWidget *dialog_message;
+
+      dialog_message = gtk_message_dialog_new (GTK_WINDOW (dialog),
+                                       GTK_DIALOG_DESTROY_WITH_PARENT,
+                                       GTK_MESSAGE_ERROR,
+                                       GTK_BUTTONS_CLOSE,
+                                               "Error: output file name is not set");
+      gtk_dialog_run (GTK_DIALOG (dialog_message));
+      gtk_widget_destroy (dialog_message);
+      break;
+    }
+
+    container = gtk_combo_box_get_active (GTK_COMBO_BOX (encode->combo));
+
+    switch (container) {
+    case 0:
+      ext = ".264";
+      break;
+    case 1:
+      ext = ".mkv";
+      break;
+#ifdef MP4_OUTPUT
+    case 2:
+      ext = ".mp4";
+      break;
+#endif
+    default:
+      ext = ".264";
+    }
+
+    file_output = g_strconcat (path_output, "/", filename_output, ext, NULL);
+    g_print ("file output : %s\n", file_output);
+
+    x264_gtk = x264_gtk_load ();
+    param = x264_gtk_param_get (x264_gtk);
+    g_free (x264_gtk);
+
+    {
+      gint width;
+      gint height;
+      gint fps_num;
+      gint fps_den;
+      gint frame_count;
+
+      width = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->width)), NULL));
+      height = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->height)), NULL));
+      fps_num = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->fps_num)), NULL));
+      fps_den = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->fps_den)), NULL));
+      frame_count = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->frame_count)), NULL));
+
+      if ((width <= 0) ||
+          (height <= 0) ||
+          (fps_num <= 0) ||
+          (fps_den <= 0) ||
+          (frame_count < 0))
+        break;
+
+      param->i_width = width;
+      param->i_height = height;
+      param->i_fps_num = fps_num;
+      param->i_fps_den = fps_den;
+      param->i_frame_total = frame_count;
+    }
+
+    if (pipe (fds) == -1)
+      break;
+
+    thread_data = (X264_Thread_Data *)g_malloc0 (sizeof (X264_Thread_Data));
+    thread_data->param = param;
+    thread_data->file_input = g_strdup (file_input);
+    thread_data->file_output = g_strdup (file_output);
+    thread_data->container = container;
+    g_free (file_output);
+
+    thread_data->io_read = g_io_channel_unix_new (fds[0]);
+    g_io_channel_set_encoding (thread_data->io_read, NULL, NULL);
+    thread_data->io_write = g_io_channel_unix_new (fds[1]);
+    g_io_channel_set_encoding (thread_data->io_write, NULL, NULL);
+
+    g_io_add_watch (thread_data->io_read, G_IO_IN,
+                    (GIOFunc)_fill_status_window, thread_data);
+
+    win_status = x264_gtk_encode_status_window (thread_data);
+    gtk_window_set_transient_for (GTK_WINDOW (win_status), GTK_WINDOW (dialog));
+    gtk_window_set_modal (GTK_WINDOW (win_status), TRUE);
+    gtk_widget_show (win_status);
+
+    thread = g_thread_create ((GThreadFunc)x264_gtk_encode_encode, thread_data, FALSE, NULL);
+
+    break;
+  }
+  case GTK_RESPONSE_CLOSE:
+  default:
+    gtk_main_quit ();
+    _encode_shutdown ((X264_Gtk_Encode *)user_data);
+  }
+}
+
+static gboolean
+_fill_status_window (GIOChannel  *io __UNUSED__,
+                     GIOCondition condition __UNUSED__,
+                     gpointer     user_data)
+{
+  gchar             str[128];
+  X264_Thread_Data *thread_data;
+  X264_Pipe_Data    pipe_data;
+  GIOStatus         status;
+  gsize             size;
+  gint              eta;
+  gdouble           progress;
+  gdouble           fps;
+
+  thread_data = (X264_Thread_Data *)user_data;
+  status = g_io_channel_read_chars (thread_data->io_read,
+                           (gchar *)&pipe_data,
+                           sizeof (X264_Pipe_Data),
+                           &size, NULL);
+  if (status != G_IO_STATUS_NORMAL) {
+    g_print ("Error ! %d %d %d\n", status, sizeof (X264_Pipe_Data), size);
+    return FALSE;
+  }
+
+  snprintf (str, 128, "%d/%d", pipe_data.frame, pipe_data.frame_total);
+  gtk_entry_set_text (GTK_ENTRY (thread_data->current_video_frame),
+                      str);
+
+  snprintf (str, 128, "%dKB",
+            pipe_data.file >> 10);
+  gtk_entry_set_text (GTK_ENTRY (thread_data->video_data),
+                      str);
+
+  fps = pipe_data.elapsed > 0 ? 1000000.0 * (gdouble)pipe_data.frame / (gdouble)pipe_data.elapsed : 0.0;
+  snprintf (str, 128, "%.2fKB/s (%.2f fps)",
+            (double) pipe_data.file * 8 * thread_data->param->i_fps_num /
+            ((double) thread_data->param->i_fps_den * pipe_data.frame * 1000),
+            fps);
+  gtk_entry_set_text (GTK_ENTRY (thread_data->video_rendering_rate),
+                      str);
+
+  snprintf (str, 128, "%lld:%02lld:%02lld",
+            (pipe_data.elapsed / 1000000) / 3600,
+            ((pipe_data.elapsed / 1000000) / 60) % 60,
+            (pipe_data.elapsed / 1000000) % 60);
+  gtk_entry_set_text (GTK_ENTRY (thread_data->time_elapsed),
+                      str);
+
+  eta = pipe_data.elapsed * (pipe_data.frame_total - pipe_data.frame) / ((int64_t)pipe_data.frame * 1000000);
+  snprintf (str, 128, "%d:%02d:%02d", eta / 3600, (eta / 60) % 60, eta % 60);
+  gtk_entry_set_text (GTK_ENTRY (thread_data->time_remaining),
+                      str);
+
+  progress = (gdouble)pipe_data.frame / (gdouble)pipe_data.frame_total;
+  gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (thread_data->progress),
+                                 progress);
+
+  snprintf (str, 128, "%0.1f%%", 100.0 * progress);
+  gtk_progress_bar_set_text (GTK_PROGRESS_BAR (thread_data->progress), str);
+
+  return TRUE;
+}
diff --git a/gtk/x264_gtk_encode_main_window.h b/gtk/x264_gtk_encode_main_window.h
new file mode 100644 (file)
index 0000000..87af2dc
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __X264_GTK_ENCODE_MAIN_WINDOW_H__
+#define __X264_GTK_ENCODE_MAIN_WINDOW_H__
+
+
+void x264_gtk_encode_main_window ();
+
+
+#endif /* __X264_GTK_ENCODE_MAIN_WINDOW_H__ */
diff --git a/gtk/x264_gtk_encode_private.h b/gtk/x264_gtk_encode_private.h
new file mode 100644 (file)
index 0000000..7958b89
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef __X264_GTK_ENCODE_PRIVATE_H__
+#define __X264_GTK_ENCODE_PRIVATE_H__
+
+
+#define __UNUSED__ __attribute__((unused))
+
+
+typedef struct X264_Thread_Data_ X264_Thread_Data;
+typedef struct X264_Pipe_Data_ X264_Pipe_Data;
+
+struct X264_Thread_Data_
+{
+  GtkWidget *current_video_frame;
+  GtkWidget *video_data;
+  GtkWidget *video_rendering_rate;
+  GtkWidget *time_elapsed;
+  GtkWidget *time_remaining;
+  GtkWidget *progress;
+
+  GtkWidget *dialog;
+  GtkWidget *button;
+
+  x264_param_t *param;
+  gchar        *file_input;
+  gchar        *file_output;
+  gint          container;
+
+  /* file descriptors */
+  GIOChannel *io_read;  /* use it with read */
+  GIOChannel *io_write; /* use it with write */
+};
+
+struct X264_Pipe_Data_ 
+{
+  int     frame;
+  int     frame_total;
+  int     file;
+  int64_t elapsed;
+};
+
+
+#endif /* __X264_GTK_ENCODE_PRIVATE_H__ */
diff --git a/gtk/x264_gtk_encode_status_window.c b/gtk/x264_gtk_encode_status_window.c
new file mode 100644 (file)
index 0000000..ce5e9eb
--- /dev/null
@@ -0,0 +1,161 @@
+#if defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ || defined __DragonFly__
+#  include <inttypes.h>
+#else
+#  include <stdint.h>
+#endif
+
+#include <gtk/gtk.h>
+
+#include "../x264.h"
+#include "x264_gtk_encode_private.h"
+
+
+/* Callbacks */
+static gboolean _delete_window_cb    (GtkWidget *widget,
+                                      GdkEvent  *event,
+                                      gpointer   user_data);
+static void     _response_window_cb  (GtkDialog *dialog,
+                                      gint       res,
+                                      gpointer   user_data);
+
+GtkWidget *
+x264_gtk_encode_status_window (X264_Thread_Data *thread_data)
+{
+  GtkWidget *win_status;
+  GtkWidget *table;
+  GtkWidget *label;
+
+  if (!thread_data) return NULL;
+
+  win_status = thread_data->dialog = gtk_dialog_new ();
+  thread_data->button = gtk_dialog_add_button (GTK_DIALOG (win_status),
+                                               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+  
+  g_signal_connect (G_OBJECT (win_status),
+                    "delete-event",
+                    G_CALLBACK (_delete_window_cb),
+                    thread_data);
+  g_signal_connect (G_OBJECT (win_status),
+                    "response",
+                    G_CALLBACK (_response_window_cb),
+                    thread_data);
+
+  table = gtk_table_new (5, 2, FALSE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
+  gtk_container_set_border_width (GTK_CONTAINER (table), 6);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (win_status)->vbox), table,
+                      FALSE, FALSE, 0);
+  gtk_widget_show (table);
+  
+  label = gtk_label_new ("Current video frame:");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
+  gtk_widget_show (label);
+  
+  thread_data->current_video_frame = gtk_entry_new ();
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             thread_data->current_video_frame,
+                             1, 2, 0, 1);
+  gtk_widget_show (thread_data->current_video_frame);
+  
+  label = gtk_label_new ("Video data:");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
+  gtk_widget_show (label);
+  
+  thread_data->video_data = gtk_entry_new ();
+  gtk_entry_set_text (GTK_ENTRY (thread_data->video_data), "0KB");
+  gtk_table_attach_defaults (GTK_TABLE (table), thread_data->video_data,
+                             1, 2, 1, 2);
+  gtk_widget_show (thread_data->video_data);
+  
+  label = gtk_label_new ("Video rendering rate:");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3);
+  gtk_widget_show (label);
+  
+  thread_data->video_rendering_rate = gtk_entry_new ();
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             thread_data->video_rendering_rate,
+                             1, 2, 2, 3);
+  gtk_widget_show (thread_data->video_rendering_rate);
+  
+  label = gtk_label_new ("Time elapsed:");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 3, 4);
+  gtk_widget_show (label);
+  
+  thread_data->time_elapsed = gtk_entry_new ();
+  gtk_table_attach_defaults (GTK_TABLE (table), thread_data->time_elapsed,
+                             1, 2, 3, 4);
+  gtk_widget_show (thread_data->time_elapsed);
+  
+  label = gtk_label_new ("Total time (estimated):");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 4, 5);
+  gtk_widget_show (label);
+  
+  thread_data->time_remaining = gtk_entry_new ();
+  gtk_table_attach_defaults (GTK_TABLE (table), thread_data->time_remaining,
+                             1, 2, 4, 5);
+  gtk_widget_show (thread_data->time_remaining);
+
+  table = gtk_table_new (1, 2, FALSE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
+  gtk_container_set_border_width (GTK_CONTAINER (table), 6);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (win_status)->vbox), table,
+                      FALSE, FALSE, 0);
+  gtk_widget_show (table);
+  
+  label = gtk_label_new ("Progress:");
+  gtk_misc_set_alignment (GTK_MISC (label),
+                          0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             label,
+                             0, 1,
+                             0, 1);
+  gtk_widget_show (label);
+  
+  thread_data->progress = gtk_progress_bar_new ();
+  gtk_table_attach_defaults (GTK_TABLE (table), thread_data->progress,
+                             1, 2, 0, 1);
+  gtk_widget_show (thread_data->progress);
+
+  return win_status;
+}
+
+static void
+_thread_data_free (X264_Thread_Data *thread_data)
+{
+  g_free (thread_data->param);
+  g_free (thread_data->file_input);
+  g_free (thread_data->file_output);
+  g_io_channel_unref (thread_data->io_read);
+  g_io_channel_unref (thread_data->io_write);
+  g_free (thread_data);
+}
+
+static gboolean
+_delete_window_cb (GtkWidget *widget,
+                   GdkEvent  *event __UNUSED__,
+                   gpointer   user_data)
+{
+  gtk_widget_destroy (widget);
+  _thread_data_free ((X264_Thread_Data *)user_data);
+  return TRUE;
+}
+
+static void
+_response_window_cb (GtkDialog *dialog,
+                     gint       res,
+                     gpointer   user_data)
+{
+  switch (res) {
+  case GTK_RESPONSE_CANCEL:
+  default:
+    gtk_widget_destroy (GTK_WIDGET (dialog));
+    _thread_data_free ((X264_Thread_Data *)user_data);
+  }
+}
diff --git a/gtk/x264_gtk_encode_status_window.h b/gtk/x264_gtk_encode_status_window.h
new file mode 100644 (file)
index 0000000..13ce035
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __X264_GTK_ENCODE_STATUS_WINDOW_H__
+#define __X264_GTK_ENCODE_STATUS_WINDOW_H__
+
+
+GtkWidget *x264_gtk_encode_status_window (X264_Thread_Data *thread_data);
+
+
+#endif /* __X264_GTK_ENCODE_STATUS_WINDOW_H__ */
diff --git a/gtk/x264_gtk_enum.h b/gtk/x264_gtk_enum.h
new file mode 100644 (file)
index 0000000..5387da6
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef __X264_GTK_ENUM_H__
+#define __X264_GTK_ENUM_H__
+
+
+typedef enum
+{
+  X264_PASS_SINGLE_BITRATE,
+  X264_PASS_SINGLE_QUANTIZER,
+  X264_PASS_MULTIPASS_1ST,
+  X264_PASS_MULTIPASS_1ST_FAST,
+  X264_PASS_MULTIPASS_NTH
+}X264_Pass;
+
+typedef enum
+{
+  X264_NONE = X264_DIRECT_PRED_NONE,
+  X264_SPATIAL = X264_DIRECT_PRED_SPATIAL,
+  X264_TEMPORAL = X264_DIRECT_PRED_TEMPORAL
+}X264_Direct_Mode;
+
+typedef enum
+{
+  X264_PD_1,
+  X264_PD_2,
+  X264_PD_3,
+  X264_PD_4,
+  X264_PD_5,
+  X264_PD_6,
+  X264_PD_6b
+}X264_Partition_Decision;
+
+typedef enum
+{
+  X264_ME_METHOD_DIAMOND = X264_ME_DIA,
+  X264_ME_METHOD_HEXAGONAL = X264_ME_HEX,
+  X264_ME_METHOD_UNEVEN_MULTIHEXA = X264_ME_UMH,
+  X264_ME_METHOD_EXHAUSTIVE = X264_ME_ESA
+}X264_Me_Method;
+
+typedef enum
+{
+  X264_DEBUG_METHOD_NONE = X264_LOG_NONE,
+  X264_DEBUG_METHOD_ERROR = X264_LOG_ERROR,
+  X264_DEBUG_METHOD_WARNING = X264_LOG_WARNING,
+  X264_DEBUG_METHOD_INFO = X264_LOG_INFO,
+  X264_DEBUG_METHOD_DEBUG = X264_LOG_DEBUG
+}X264_Debug_Method;
+
+
+#endif /* __X264_GTK_ENUM_H__ */
diff --git a/gtk/x264_gtk_mb.c b/gtk/x264_gtk_mb.c
new file mode 100644 (file)
index 0000000..a494d38
--- /dev/null
@@ -0,0 +1,130 @@
+#include <gtk/gtk.h>
+
+#include "x264_gtk_private.h"
+
+
+GtkWidget *
+_mb_page (X264_Gui_Config *config)
+{
+  GtkWidget   *vbox;
+  GtkWidget   *frame;
+  GtkWidget   *vbox2;
+  GtkWidget   *table;
+  GtkWidget   *label;
+
+  vbox = gtk_vbox_new (FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
+
+  /* Partitions */
+  frame = gtk_frame_new ("Partitions");
+  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 6);
+  gtk_widget_show (frame);
+
+  vbox2 = gtk_vbox_new (FALSE, 6);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox2), 6);
+  gtk_container_add (GTK_CONTAINER (frame), vbox2);
+  gtk_widget_show (vbox2);
+
+  config->mb.partitions.transform_8x8 = gtk_check_button_new_with_label ("8x8 Transform");
+  gtk_box_pack_start (GTK_BOX (vbox2), config->mb.partitions.transform_8x8, FALSE, TRUE, 0);
+  gtk_widget_show (config->mb.partitions.transform_8x8);
+
+  config->mb.partitions.pframe_search_8 = gtk_check_button_new_with_label ("8x16, 16x8 and 8x8 P-frame search");
+  gtk_box_pack_start (GTK_BOX (vbox2), config->mb.partitions.pframe_search_8, FALSE, TRUE, 0);
+  gtk_widget_show (config->mb.partitions.pframe_search_8);
+
+  config->mb.partitions.bframe_search_8 = gtk_check_button_new_with_label ("8x16, 16x8 and 8x8 B-frame search");
+  gtk_box_pack_start (GTK_BOX (vbox2), config->mb.partitions.bframe_search_8, FALSE, TRUE, 0);
+  gtk_widget_show (config->mb.partitions.bframe_search_8);
+
+  config->mb.partitions.pframe_search_4 = gtk_check_button_new_with_label ("4x8, 8x4 and 4x4 P-frame search");
+  gtk_box_pack_start (GTK_BOX (vbox2), config->mb.partitions.pframe_search_4, FALSE, TRUE, 0);
+  gtk_widget_show (config->mb.partitions.pframe_search_4);
+
+  config->mb.partitions.inter_search_8 = gtk_check_button_new_with_label ("8x8 Intra search");
+  gtk_box_pack_start (GTK_BOX (vbox2), config->mb.partitions.inter_search_8, FALSE, TRUE, 0);
+  gtk_widget_show (config->mb.partitions.inter_search_8);
+
+  config->mb.partitions.inter_search_4 = gtk_check_button_new_with_label ("4x4 Intra search");
+  gtk_box_pack_start (GTK_BOX (vbox2), config->mb.partitions.inter_search_4, FALSE, TRUE, 0);
+  gtk_widget_show (config->mb.partitions.inter_search_4);
+
+  /* B-Frames */
+  frame = gtk_frame_new ("B-Frames");
+  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 6);
+  gtk_widget_show (frame);
+
+  table = gtk_table_new (5, 2, TRUE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+  gtk_container_set_border_width (GTK_CONTAINER (table), 6);
+  gtk_container_add (GTK_CONTAINER (frame), table);
+  gtk_widget_show (table);
+
+  label = gtk_label_new ("Max consecutive");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 0, 1);
+  gtk_widget_show (label);
+
+  config->mb.bframes.max_consecutive = gtk_entry_new_with_max_length (3);
+  gtk_table_attach_defaults (GTK_TABLE (table), config->mb.bframes.max_consecutive,
+                             1, 2, 0, 1);
+  gtk_widget_show (config->mb.bframes.max_consecutive);
+
+  label = gtk_label_new ("Bias");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 1, 2);
+  gtk_widget_show (label);
+
+  config->mb.bframes.bias = gtk_hscale_new_with_range (-100.0, 100.0, 1.0);
+  gtk_scale_set_digits (GTK_SCALE (config->mb.bframes.bias), 0);
+  gtk_scale_set_value_pos (GTK_SCALE (config->mb.bframes.bias), GTK_POS_RIGHT);
+  gtk_table_attach_defaults (GTK_TABLE (table), config->mb.bframes.bias,
+                             1, 2, 1, 2);
+  gtk_widget_show (config->mb.bframes.bias);
+
+  config->mb.bframes.use_as_reference = gtk_check_button_new_with_label ("Use as references");
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             config->mb.bframes.use_as_reference,
+                             0, 1, 2, 3);
+  gtk_widget_show (config->mb.bframes.use_as_reference);
+
+  config->mb.bframes.bidir_me = gtk_check_button_new_with_label ("Bidirectional ME");
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             config->mb.bframes.bidir_me,
+                             1, 2, 2, 3);
+  gtk_widget_show (config->mb.bframes.bidir_me);
+
+  config->mb.bframes.adaptive = gtk_check_button_new_with_label ("Adaptive");
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             config->mb.bframes.adaptive,
+                             0, 1, 3, 4);
+  gtk_widget_show (config->mb.bframes.adaptive);
+
+  config->mb.bframes.weighted_biprediction = gtk_check_button_new_with_label ("Weighted biprediction");
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             config->mb.bframes.weighted_biprediction,
+                             1, 2, 3, 4);
+  gtk_widget_show (config->mb.bframes.weighted_biprediction);
+
+  label = gtk_label_new ("Direct mode");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 4, 5);
+  gtk_widget_show (label);
+
+  config->mb.bframes.direct_mode = gtk_combo_box_new_text ();
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->mb.bframes.direct_mode),
+                             "None");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->mb.bframes.direct_mode),
+                             "Spatial");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->mb.bframes.direct_mode),
+                             "Temporal");
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             config->mb.bframes.direct_mode,
+                             1, 2, 4, 5);
+  gtk_widget_show (config->mb.bframes.direct_mode);
+
+  return vbox;
+}
diff --git a/gtk/x264_gtk_mb.h b/gtk/x264_gtk_mb.h
new file mode 100644 (file)
index 0000000..4649624
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __X264_GTK_MB_H__
+#define __X264_GTK_MB_H__
+
+
+GtkWidget *_mb_page (X264_Gui_Config *config);
+
+
+#endif /* __X264_GTK_MB_H__ */
diff --git a/gtk/x264_gtk_more.c b/gtk/x264_gtk_more.c
new file mode 100644 (file)
index 0000000..aa569d9
--- /dev/null
@@ -0,0 +1,343 @@
+#include <gtk/gtk.h>
+
+#include "x264_gtk_private.h"
+
+
+/* Callbacks */
+static void _more_deblocking_filter (GtkToggleButton *button,
+                                     gpointer         user_data);
+static void _more_cabac             (GtkToggleButton *button,
+                                     gpointer         user_data);
+
+
+GtkWidget *
+_more_page (X264_Gui_Config *config)
+{
+  GtkWidget     *vbox;
+  GtkWidget     *frame;
+  GtkWidget     *hbox;
+  GtkWidget     *table;
+  GtkWidget     *label;
+  GtkRequisition size;
+  GtkRequisition size2;
+  GtkRequisition size3;
+  GtkRequisition size4;
+  GtkRequisition size5;
+
+  label = gtk_entry_new_with_max_length (3);
+  gtk_widget_size_request (label, &size);
+  gtk_widget_destroy (GTK_WIDGET (label));
+
+  label = gtk_check_button_new_with_label ("Deblocking Filter");
+  gtk_widget_size_request (label, &size2);
+  gtk_widget_destroy (GTK_WIDGET (label));
+
+  label = gtk_label_new ("Partition decision");
+  gtk_widget_size_request (label, &size3);
+  gtk_widget_destroy (GTK_WIDGET (label));
+
+  label = gtk_label_new ("Threshold");
+  gtk_widget_size_request (label, &size5);
+  gtk_widget_destroy (GTK_WIDGET (label));
+
+  vbox = gtk_vbox_new (FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
+
+  /* Motion Estimation */
+  frame = gtk_frame_new ("Motion Estimation");
+  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 6);
+  gtk_widget_show (frame);
+
+  table = gtk_table_new (4, 3, TRUE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
+  gtk_container_set_border_width (GTK_CONTAINER (table), 6);
+  gtk_container_add (GTK_CONTAINER (frame), table);
+  gtk_widget_show (table);
+
+  label = gtk_label_new ("Partition decision");
+  gtk_widget_set_size_request (label, size2.width, size3.height);
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 2, 0, 1);
+  gtk_widget_show (label);
+
+  config->more.motion_estimation.partition_decision = gtk_combo_box_new_text ();
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.motion_estimation.partition_decision),
+                             "1 (Fastest)");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.motion_estimation.partition_decision),
+                             "2");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.motion_estimation.partition_decision),
+                             "3");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.motion_estimation.partition_decision),
+                             "4");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.motion_estimation.partition_decision),
+                             "5 (High quality)");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.motion_estimation.partition_decision),
+                             "6 (RDO)");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.motion_estimation.partition_decision),
+                             "6b (RDO on B frames)");
+  gtk_table_attach_defaults (GTK_TABLE (table), config->more.motion_estimation.partition_decision,
+                             1, 3, 0, 1);
+  gtk_widget_show (config->more.motion_estimation.partition_decision);
+
+  label = gtk_label_new ("Method");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 2, 1, 2);
+  gtk_widget_show (label);
+
+  config->more.motion_estimation.method = gtk_combo_box_new_text ();
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.motion_estimation.method),
+                             "Diamond Search");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.motion_estimation.method),
+                             "Hexagonal Search");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.motion_estimation.method),
+                             "Uneven Multi-Hexagon");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.motion_estimation.method),
+                             "Exhaustive search");
+  gtk_table_attach_defaults (GTK_TABLE (table), config->more.motion_estimation.method,
+                             1, 3, 1, 2);
+  gtk_widget_show (config->more.motion_estimation.method);
+
+  label = gtk_label_new ("Range");
+  gtk_widget_size_request (label, &size4);
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 2, 3);
+  gtk_widget_show (label);
+
+  config->more.motion_estimation.range = gtk_entry_new_with_max_length (3);
+  gtk_widget_set_size_request (config->more.motion_estimation.range,
+                               20, size.height);
+  gtk_table_attach_defaults (GTK_TABLE (table), config->more.motion_estimation.range,
+                             1, 2, 2, 3);
+  gtk_widget_show (config->more.motion_estimation.range);
+
+  config->more.motion_estimation.chroma_me = gtk_check_button_new_with_label ("Chroma ME");
+  gtk_table_attach_defaults (GTK_TABLE (table), config->more.motion_estimation.chroma_me,
+                             2, 3, 2, 3);
+  gtk_widget_show (config->more.motion_estimation.chroma_me);
+
+  label = gtk_label_new ("Max Ref. frames");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 3, 4);
+  gtk_widget_show (label);
+
+  config->more.motion_estimation.max_ref_frames = gtk_entry_new_with_max_length (3);
+  gtk_widget_set_size_request (config->more.motion_estimation.max_ref_frames,
+                               20, size.height);
+  gtk_table_attach_defaults (GTK_TABLE (table), config->more.motion_estimation.max_ref_frames,
+                             1, 2, 3, 4);
+  gtk_widget_show (config->more.motion_estimation.max_ref_frames);
+
+  config->more.motion_estimation.mixed_refs = gtk_check_button_new_with_label ("Mixed Refs");
+  gtk_table_attach_defaults (GTK_TABLE (table), config->more.motion_estimation.mixed_refs,
+                             2, 3, 3, 4);
+  gtk_widget_show (config->more.motion_estimation.mixed_refs);
+
+  /* Misc. Options */
+  frame = gtk_frame_new ("Misc. Options");
+  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 6);
+  gtk_widget_show (frame);
+
+  table = gtk_table_new (5, 4, FALSE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
+  gtk_container_set_border_width (GTK_CONTAINER (table), 6);
+  gtk_container_add (GTK_CONTAINER (frame), table);
+  gtk_widget_show (table);
+
+  label = gtk_label_new ("Sample AR");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 0, 1);
+  gtk_widget_show (label);
+
+  hbox = gtk_hbox_new (TRUE, 6);
+  gtk_table_attach_defaults (GTK_TABLE (table), hbox,
+                             1, 2, 0, 1);
+  gtk_widget_show (hbox);
+
+  config->more.misc.sample_ar_x = gtk_entry_new_with_max_length (3);
+  gtk_widget_set_size_request (config->more.misc.sample_ar_x, 25, size.height);
+  gtk_box_pack_start (GTK_BOX (hbox), config->more.misc.sample_ar_x, FALSE, TRUE, 0);
+  gtk_widget_show (config->more.misc.sample_ar_x);
+
+  config->more.misc.sample_ar_y = gtk_entry_new_with_max_length (3);
+  gtk_widget_set_size_request (config->more.misc.sample_ar_y, 25, size.height);
+  gtk_box_pack_start (GTK_BOX (hbox), config->more.misc.sample_ar_y, FALSE, TRUE, 0);
+  gtk_widget_show (config->more.misc.sample_ar_y);
+
+  label = gtk_label_new ("Threads");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             2, 3, 0, 1);
+  gtk_widget_show (label);
+
+  config->more.misc.threads = gtk_entry_new_with_max_length (3);
+  gtk_widget_set_size_request (config->more.misc.threads, size5.width, size.height);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             config->more.misc.threads,
+                             3, 4, 0, 1);
+  gtk_widget_show (config->more.misc.threads);
+
+  config->more.misc.cabac = gtk_check_button_new_with_label ("CABAC");
+  gtk_widget_set_size_request (config->more.misc.cabac, size5.width, size.height);
+  g_signal_connect (G_OBJECT (config->more.misc.cabac),
+                    "toggled",
+                    G_CALLBACK (_more_cabac), config);
+  gtk_table_attach_defaults (GTK_TABLE (table), config->more.misc.cabac,
+                             0, 1, 1, 2);
+  gtk_widget_show (config->more.misc.cabac);
+
+  label = gtk_label_new ("Trellis");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             1, 2, 1, 2);
+  gtk_widget_show (label);
+
+  config->more.misc.trellis = gtk_combo_box_new_text ();
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.misc.trellis),
+                             "Disabled");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.misc.trellis),
+                             "Enabled (once)");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.misc.trellis),
+                             "Enabled (mode decision)");
+  gtk_table_attach_defaults (GTK_TABLE (table), config->more.misc.trellis,
+                             2, 4, 1, 2);
+  gtk_widget_show (config->more.misc.trellis);
+
+  label = gtk_label_new ("Noise reduction");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 2, 3);
+  gtk_widget_show (label);
+
+  config->more.misc.noise_reduction = gtk_entry_new_with_max_length (3);
+  gtk_widget_set_size_request (config->more.misc.noise_reduction, size5.width, size.height);
+  gtk_table_attach_defaults (GTK_TABLE (table), config->more.misc.noise_reduction,
+                             1, 2, 2, 3);
+  gtk_widget_show (config->more.misc.noise_reduction);
+
+  config->more.misc.df.deblocking_filter = gtk_check_button_new_with_label ("Deblocking Filter");
+  g_signal_connect (G_OBJECT (config->more.misc.df.deblocking_filter),
+                    "toggled",
+                    G_CALLBACK (_more_deblocking_filter), config);
+  gtk_table_attach_defaults (GTK_TABLE (table), config->more.misc.df.deblocking_filter,
+                             0, 1, 3, 4);
+  gtk_widget_show (config->more.misc.df.deblocking_filter);
+
+  label = gtk_label_new ("Strength");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_widget_set_size_request (label, size5.width, size4.height);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             1, 2, 3, 4);
+  gtk_widget_show (label);
+
+  config->more.misc.df.strength = gtk_hscale_new_with_range (-6.0, 6.0, 1.0);
+  gtk_widget_size_request (config->more.misc.df.strength, &size4);
+  gtk_scale_set_digits (GTK_SCALE (config->more.misc.df.strength), 0);
+  gtk_scale_set_value_pos (GTK_SCALE (config->more.misc.df.strength), GTK_POS_RIGHT);
+  //  gtk_widget_set_size_request (config->more.misc.df.strength, size5.width, size4.height);
+  gtk_table_attach_defaults (GTK_TABLE (table), config->more.misc.df.strength,
+                             2, 4, 3, 4);
+  gtk_widget_show (config->more.misc.df.strength);
+
+  label = gtk_label_new ("Threshold");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_widget_set_size_request (label, size5.width, size4.height);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             1, 2, 4, 5);
+  gtk_widget_show (label);
+
+  config->more.misc.df.threshold = gtk_hscale_new_with_range (-6.0, 6.0, 1.0);
+  gtk_scale_set_digits (GTK_SCALE (config->more.misc.df.threshold), 0);
+  gtk_scale_set_value_pos (GTK_SCALE (config->more.misc.df.threshold), GTK_POS_RIGHT);
+  gtk_table_attach_defaults (GTK_TABLE (table), config->more.misc.df.threshold,
+                             2, 4, 4, 5);
+  gtk_widget_show (config->more.misc.df.threshold);
+
+  /* Debug */
+  frame = gtk_frame_new ("Debug");
+  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 6);
+  gtk_widget_show (frame);
+
+  table = gtk_table_new (2, 2, TRUE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+  gtk_container_set_border_width (GTK_CONTAINER (table), 6);
+  gtk_container_add (GTK_CONTAINER (frame), table);
+  gtk_widget_show (table);
+
+  label = gtk_label_new ("Log level");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_widget_set_size_request (label, size2.width, size3.height);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 0, 1);
+  gtk_widget_show (label);
+
+  config->more.debug.log_level = gtk_combo_box_new_text ();
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.debug.log_level),
+                             "None");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.debug.log_level),
+                             "Error");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.debug.log_level),
+                             "Warning");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.debug.log_level),
+                             "Info");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (config->more.debug.log_level),
+                             "Debug");
+  gtk_table_attach_defaults (GTK_TABLE (table), config->more.debug.log_level,
+                             1, 2, 0, 1);
+  gtk_widget_show (config->more.debug.log_level);
+
+  label = gtk_label_new ("FourCC");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 1, 2);
+  gtk_widget_show (label);
+
+  config->more.debug.fourcc = gtk_entry_new_with_max_length (4);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             config->more.debug.fourcc,
+                             1, 2, 1, 2);
+  gtk_widget_show (config->more.debug.fourcc);
+
+
+
+  return vbox;
+}
+
+/* Callbacks */
+static void
+_more_deblocking_filter (GtkToggleButton *button,
+                         gpointer         user_data)
+{
+  X264_Gui_Config *config;
+
+  config = (X264_Gui_Config *)user_data;
+
+  if (gtk_toggle_button_get_active (button)) {
+    gtk_widget_set_sensitive (config->more.misc.df.strength, TRUE);
+    gtk_widget_set_sensitive (config->more.misc.df.threshold, TRUE);
+  }
+  else {
+    gtk_widget_set_sensitive (config->more.misc.df.strength, FALSE);
+    gtk_widget_set_sensitive (config->more.misc.df.threshold, FALSE);
+  }
+}
+
+static void
+_more_cabac (GtkToggleButton *button,
+             gpointer         user_data)
+{
+  X264_Gui_Config *config;
+
+  config = (X264_Gui_Config *)user_data;
+
+  if (gtk_toggle_button_get_active (button))
+    gtk_widget_set_sensitive (config->more.misc.trellis, TRUE);
+  else
+    gtk_widget_set_sensitive (config->more.misc.trellis, FALSE);
+}
diff --git a/gtk/x264_gtk_more.h b/gtk/x264_gtk_more.h
new file mode 100644 (file)
index 0000000..f94134d
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __X264_GTK_MORE_H__
+#define __X264_GTK_MORE_H__
+
+
+GtkWidget *_more_page (X264_Gui_Config *config);
+
+
+#endif /* __X264_GTK_MORE_H__ */
diff --git a/gtk/x264_gtk_private.h b/gtk/x264_gtk_private.h
new file mode 100644 (file)
index 0000000..cff9052
--- /dev/null
@@ -0,0 +1,146 @@
+#ifndef __X264_GTK_PRIVATE_H__
+#define __X264_GTK_PRIVATE_H__
+
+
+#define __UNUSED__ __attribute__((unused))
+
+
+typedef struct Bitrate_ Bitrate;
+typedef struct Rate_Control_ Rate_Control;
+typedef struct MB_ MB;
+typedef struct More_ More;
+typedef struct Zones_ Zones;
+typedef struct X264_Gui_Config_ X264_Gui_Config;
+typedef struct X264_Gui_Zone_ X264_Gui_Zone;
+
+struct Bitrate_
+{
+  GtkWidget *pass;
+  GtkWidget *label;
+  GtkWidget *w_quantizer;
+  GtkWidget *w_average_bitrate;
+  GtkWidget *w_target_bitrate;
+
+  GtkWidget *update_statfile;
+  GtkWidget *statsfile_name;
+};
+
+struct Rate_Control_
+{
+  /* bitrate */
+  struct
+  {
+    GtkWidget *keyframe_boost;
+    GtkWidget *bframes_reduction;
+    GtkWidget *bitrate_variability;
+  }bitrate;
+
+  /* Quantization Limits */
+  struct
+  {
+    GtkWidget *min_qp;
+    GtkWidget *max_qp;
+    GtkWidget *max_qp_step;
+  }quantization_limits;
+
+  /* Scene Cuts */
+  struct
+  {
+    GtkWidget *scene_cut_threshold;
+    GtkWidget *min_idr_frame_interval;
+    GtkWidget *max_idr_frame_interval;
+  }scene_cuts;
+
+};
+
+struct MB_
+{
+  /* Partitions */
+  struct
+  {
+    GtkWidget *transform_8x8;
+    GtkWidget *pframe_search_8;
+    GtkWidget *bframe_search_8;
+    GtkWidget *pframe_search_4;
+    GtkWidget *inter_search_8;
+    GtkWidget *inter_search_4;
+  }partitions;
+
+  /* B-frames */
+  struct
+  {
+    GtkWidget *use_as_reference;
+    GtkWidget *bidir_me;
+    GtkWidget *adaptive;
+    GtkWidget *weighted_biprediction;
+    GtkWidget *max_consecutive;
+    GtkWidget *bias;
+    GtkWidget *direct_mode;
+  }bframes;
+
+};
+
+struct More_
+{
+  /* Motion estimation */
+  struct
+  {
+    GtkWidget *partition_decision;
+    GtkWidget *method;
+    GtkWidget *range;
+    GtkWidget *chroma_me;
+    GtkWidget *max_ref_frames;
+    GtkWidget *mixed_refs;
+  }motion_estimation;
+
+  /* Misc. Options */
+  struct
+  {
+    GtkWidget *sample_ar_x;
+    GtkWidget *sample_ar_y;
+    GtkWidget *threads;
+    GtkWidget *cabac;
+    GtkWidget *trellis;
+    GtkWidget *noise_reduction;
+
+    struct
+    {
+      GtkWidget *deblocking_filter;
+      GtkWidget *strength;
+      GtkWidget *threshold;
+    }df;
+
+  }misc;
+
+  struct
+  {
+    GtkWidget *log_level;
+    GtkWidget *fourcc;
+  }debug;
+
+};
+
+struct Zones_
+{
+  GtkWidget *list_zones;
+};
+
+struct X264_Gui_Config_
+{
+  Bitrate      bitrate;
+  Rate_Control rate_control;
+  MB           mb;
+  More         more;
+  Zones        zones;
+};
+
+struct X264_Gui_Zone_
+{
+  GtkWidget *entry_start_frame;
+  GtkWidget *radio_qp;
+  GtkWidget *entry_qp;
+  GtkWidget *entry_weight;
+};
+
+
+#endif /* __X264_GTK_PRIVATE_H__ */
diff --git a/gtk/x264_gtk_rc.c b/gtk/x264_gtk_rc.c
new file mode 100644 (file)
index 0000000..cdff2a1
--- /dev/null
@@ -0,0 +1,208 @@
+#include <gtk/gtk.h>
+
+#include "x264_gtk_private.h"
+
+
+/* Callbacks */
+static void _insert_numeric (GtkEditable *editable,
+                             const gchar *text,
+                             gint         length,
+                             gint        *position,
+                             gpointer     data);
+
+GtkWidget *
+_rate_control_page (X264_Gui_Config *config)
+{
+  GtkWidget     *vbox;
+  GtkWidget     *frame;
+  GtkWidget     *table;
+  GtkWidget     *label;
+
+  vbox = gtk_vbox_new (FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
+
+  /* bitrate */
+  frame = gtk_frame_new ("Bitrate");
+  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 6);
+  gtk_widget_show (frame);
+
+  table = gtk_table_new (3, 2, TRUE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+  gtk_container_set_border_width (GTK_CONTAINER (table), 6);
+  gtk_container_add (GTK_CONTAINER (frame), table);
+  gtk_widget_show (table);
+
+  label = gtk_label_new ("Keyframe boost (%)");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 0, 1);
+  gtk_widget_show (label);
+
+  config->rate_control.bitrate.keyframe_boost = gtk_entry_new_with_max_length (3);
+  g_signal_connect (G_OBJECT (config->rate_control.bitrate.keyframe_boost),
+                    "insert-text",
+                    G_CALLBACK (_insert_numeric),
+                    NULL);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             config->rate_control.bitrate.keyframe_boost,
+                             1, 2, 0, 1);
+  gtk_widget_show (config->rate_control.bitrate.keyframe_boost);
+
+  label = gtk_label_new ("B-frames reduction (%)");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 1, 2);
+  gtk_widget_show (label);
+
+  config->rate_control.bitrate.bframes_reduction = gtk_entry_new_with_max_length (5);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             config->rate_control.bitrate.bframes_reduction,
+                             1, 2, 1, 2);
+  gtk_widget_show (config->rate_control.bitrate.bframes_reduction);
+
+  label = gtk_label_new ("Bitrate variability (%)");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 2, 3);
+  gtk_widget_show (label);
+
+  config->rate_control.bitrate.bitrate_variability = gtk_entry_new_with_max_length (3);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             config->rate_control.bitrate.bitrate_variability,
+                             1, 2, 2, 3);
+  gtk_widget_show (config->rate_control.bitrate.bitrate_variability);
+
+  /* Quantization limits */
+  frame = gtk_frame_new ("Quantization limits");
+  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 6);
+  gtk_widget_show (frame);
+
+  table = gtk_table_new (3, 2, TRUE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+  gtk_container_set_border_width (GTK_CONTAINER (table), 6);
+  gtk_container_add (GTK_CONTAINER (frame), table);
+  gtk_widget_show (table);
+
+  label = gtk_label_new ("Min QP");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 0, 1);
+  gtk_widget_show (label);
+
+  config->rate_control.quantization_limits.min_qp = gtk_entry_new_with_max_length (3);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             config->rate_control.quantization_limits.min_qp,
+                             1, 2, 0, 1);
+  gtk_widget_show (config->rate_control.quantization_limits.min_qp);
+
+  label = gtk_label_new ("Max QP");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 1, 2);
+  gtk_widget_show (label);
+
+  config->rate_control.quantization_limits.max_qp = gtk_entry_new_with_max_length (3);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             config->rate_control.quantization_limits.max_qp,
+                             1, 2, 1, 2);
+  gtk_widget_show (config->rate_control.quantization_limits.max_qp);
+
+  label = gtk_label_new ("Max QP Step");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 2, 3);
+  gtk_widget_show (label);
+
+  config->rate_control.quantization_limits.max_qp_step = gtk_entry_new_with_max_length (3);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             config->rate_control.quantization_limits.max_qp_step,
+                             1, 2, 2, 3);
+  gtk_widget_show (config->rate_control.quantization_limits.max_qp_step);
+
+  /* Scene Cuts */
+  frame = gtk_frame_new ("Scene Cuts");
+  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 6);
+  gtk_widget_show (frame);
+
+  table = gtk_table_new (3, 2, TRUE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+  gtk_container_set_border_width (GTK_CONTAINER (table), 6);
+  gtk_container_add (GTK_CONTAINER (frame), table);
+  gtk_widget_show (table);
+
+  label = gtk_label_new ("Scene Cut Threshold");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 0, 1);
+  gtk_widget_show (label);
+
+  config->rate_control.scene_cuts.scene_cut_threshold = gtk_entry_new_with_max_length (3);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             config->rate_control.scene_cuts.scene_cut_threshold,
+                             1, 2, 0, 1);
+  gtk_widget_show (config->rate_control.scene_cuts.scene_cut_threshold);
+
+  label = gtk_label_new ("Min IDR-frame interval");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 1, 2);
+  gtk_widget_show (label);
+
+  config->rate_control.scene_cuts.min_idr_frame_interval = gtk_entry_new_with_max_length (3);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             config->rate_control.scene_cuts.min_idr_frame_interval,
+                             1, 2, 1, 2);
+  gtk_widget_show (config->rate_control.scene_cuts.min_idr_frame_interval);
+
+  label = gtk_label_new ("Max IDR-frame interval");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label,
+                             0, 1, 2, 3);
+  gtk_widget_show (label);
+
+  config->rate_control.scene_cuts.max_idr_frame_interval = gtk_entry_new_with_max_length (3);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                             config->rate_control.scene_cuts.max_idr_frame_interval,
+                             1, 2, 2, 3);
+  gtk_widget_show (config->rate_control.scene_cuts.max_idr_frame_interval);
+
+
+  return vbox;
+}
+
+static void
+_insert_numeric (GtkEditable *editable,
+                 const gchar *text,
+                 gint         length,
+                 gint        *position,
+                 gpointer     data)
+{
+  gint i;
+  gint j;
+  gchar *result;
+
+  result = (gchar *)g_malloc (sizeof (gchar) * (length + 1));
+  if (!result)
+    return;
+
+  for (i = 0, j = 0; i < length; i++)
+    {
+      if (g_ascii_isdigit (text[i]))
+        {
+          result[j] = text[i];
+          j++;
+        }
+    }
+  result[j] = '\0';
+
+  g_signal_handlers_block_by_func (editable,
+                                  (gpointer) _insert_numeric, data);
+  gtk_editable_insert_text (editable, result, j, position);
+  g_signal_handlers_unblock_by_func (editable,
+                                     (gpointer) _insert_numeric, data);
+
+  g_signal_stop_emission_by_name (editable, "insert-text");
+
+  g_free (result);
+}
+
diff --git a/gtk/x264_gtk_rc.h b/gtk/x264_gtk_rc.h
new file mode 100644 (file)
index 0000000..865196f
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __X264_GTK_RC_H__
+#define __X264_GTK_RC_H__
+
+
+GtkWidget *_rate_control_page (X264_Gui_Config *config);
+
+
+#endif /* __X264_GTK_RC_H__ */