x264_gtk_encode_main_window.c
上传用户:hjq518
上传日期:2021-12-09
资源大小:5084k
文件大小:28k
源码类别:

Audio

开发平台:

Visual C++

  1. /*****************************************************************************
  2.  * x264_gtk_encode_main_window.c: h264 gtk encoder frontend
  3.  *****************************************************************************
  4.  * Copyright (C) 2006 Vincent Torri
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  19.  *****************************************************************************/
  20. #if defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ || defined __DragonFly__
  21. #  include <inttypes.h>
  22. #else
  23. #  include <stdint.h>
  24. #endif
  25. #include <unistd.h>
  26. #ifdef _WIN32 /* Needed to define _O_BINARY */
  27. #  include <fcntl.h>
  28. #  define strncasecmp _strnicmp
  29. #endif
  30. #include <errno.h>
  31. #include <string.h>
  32. #include <sys/stat.h>  /* For stat */
  33. #include <gtk/gtk.h>
  34. #include "../x264.h"
  35. #include "../config.h"
  36. #include "x264_icon.h"
  37. #include "x264_gtk.h"
  38. #include "x264_gtk_i18n.h"
  39. #include "x264_gtk_demuxers.h"
  40. #include "x264_gtk_encode_private.h"
  41. #include "x264_gtk_encode_encode.h"
  42. #include "x264_gtk_encode_status_window.h"
  43. typedef struct X264_Gtk_Encode_ X264_Gtk_Encode;
  44. struct X264_Gtk_Encode_
  45. {
  46.   GtkWidget         *main_dialog;
  47.   /* input */
  48.   X264_Demuxer_Type  container;
  49.   guint64            size; /* For YUV formats */
  50.   GtkWidget         *file_input;
  51.   GtkWidget         *width;
  52.   GtkWidget         *height;
  53.   GtkWidget         *fps_num;
  54.   GtkWidget         *fps_den;
  55.   GtkWidget         *frame_count;
  56.   /* output */
  57.   GtkWidget         *path_output;
  58.   GtkWidget         *file_output;
  59.   GtkWidget         *combo;
  60. };
  61. /* Callbacks */
  62. static gboolean x264_delete_window_cb    (GtkWidget   *widget,
  63.                                       GdkEvent    *event,
  64.                                       gpointer     user_data);
  65. static void     x264_configure_window_cb (GtkButton   *button,
  66.                                       gpointer     user_data);
  67. static void     x264_chooser_window_cb   (GtkDialog   *dialog,
  68.                                       gint         res,
  69.                                       gpointer     user_data);
  70. static void     x264_response_window_cb  (GtkDialog   *dialog,
  71.                                       gint         res,
  72.                                       gpointer     user_data);
  73. static void     x264_dimension_entry_cb  (GtkEditable *editable,
  74.                                       gpointer     user_data);
  75. static gboolean x264_fill_status_window (GIOChannel  *io,
  76.                                      GIOCondition condition,
  77.                                      gpointer     user_data);
  78. /* Code */
  79. guint64
  80. x264_file_size(const char* name)
  81. {
  82.   struct stat buf;
  83.   memset(&buf, 0, sizeof(struct stat));
  84.   if (stat(name, &buf) < 0)
  85.   {
  86.     fprintf(stderr, _("Can't stat filen"));
  87.     return 0;
  88.   }
  89.   return buf.st_size;
  90. }
  91. void
  92. x264_gtk_encode_main_window ()
  93. {
  94.   GtkWidget       *dialog;
  95.   GtkWidget       *frame;
  96.   GtkWidget       *button;
  97.   GtkWidget       *table;
  98.   GtkWidget       *label;
  99.   GtkFileChooser  *chooser;
  100.   GtkFileFilter   *filter;
  101.   GdkPixbuf       *icon;
  102.   X264_Gtk_Encode *encode;
  103.   encode = (X264_Gtk_Encode *)g_malloc0 (sizeof (X264_Gtk_Encode));
  104.   dialog = gtk_dialog_new_with_buttons (_("X264 Gtk Encoder"),
  105.                                         NULL, 0,
  106.                                         NULL);
  107.   icon = gdk_pixbuf_new_from_inline (-1, x264_icon,
  108.                                         FALSE, NULL);
  109.   gtk_window_set_icon (GTK_WINDOW (dialog), icon);
  110.   g_signal_connect (G_OBJECT (dialog),
  111.                     "delete-event",
  112.                     G_CALLBACK (x264_delete_window_cb),
  113.                     encode);
  114.   g_signal_connect (G_OBJECT (dialog),
  115.                     "response",
  116.                     G_CALLBACK (x264_response_window_cb),
  117.                     encode);
  118.   encode->main_dialog = dialog;
  119.   button = gtk_button_new_with_label (_("Configure"));
  120.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), button, FALSE, TRUE, 6);
  121.   g_signal_connect (G_OBJECT (button),
  122.                     "clicked",
  123.                     G_CALLBACK (x264_configure_window_cb),
  124.                     dialog);
  125.   gtk_widget_show (button);
  126.   gtk_dialog_add_buttons (GTK_DIALOG (dialog),
  127.                           GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
  128.                           GTK_STOCK_EXECUTE, GTK_RESPONSE_APPLY,
  129.                           NULL);
  130.   /* input */
  131.   frame = gtk_frame_new (_("Input file"));
  132.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame, FALSE, TRUE, 6);
  133.   gtk_widget_show (frame);
  134.   table = gtk_table_new (6, 2, TRUE);
  135.   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
  136.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  137.   gtk_container_set_border_width (GTK_CONTAINER (table), 6);
  138.   gtk_container_add (GTK_CONTAINER (frame), table);
  139.   gtk_widget_show (table);
  140.   label = gtk_label_new (_("Input file:"));
  141.   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  142.   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
  143.   gtk_widget_show (label);
  144.   chooser = (GtkFileChooser*)
  145.       gtk_file_chooser_dialog_new(_("Select a file"),
  146.                                   GTK_WINDOW(dialog),
  147.                                   GTK_FILE_CHOOSER_ACTION_OPEN,
  148.                                   GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
  149.                                   GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
  150.                                   NULL);
  151.   gtk_file_chooser_set_current_folder (chooser, g_get_home_dir ());
  152.    /* All supported */
  153.   filter = gtk_file_filter_new ();
  154.   gtk_file_filter_set_name (filter, _("All supported"));
  155.   gtk_file_filter_add_pattern (filter, "*.yuv");
  156.   gtk_file_filter_add_pattern (filter, "*.cif");
  157.   gtk_file_filter_add_pattern (filter, "*.qcif");
  158.   gtk_file_filter_add_pattern (filter, "*.y4m");
  159. #ifdef AVIS_INPUT
  160.   gtk_file_filter_add_pattern (filter, "*.avs");
  161.   gtk_file_filter_add_pattern (filter, "*.avi");
  162. #endif
  163.   gtk_file_chooser_add_filter (chooser, filter);
  164.   /* YUV filter */
  165.   filter = gtk_file_filter_new ();
  166.   gtk_file_filter_set_name (filter, _("YUV sequence"));
  167.   gtk_file_filter_add_pattern (filter, "*.yuv");
  168.   gtk_file_chooser_add_filter (chooser, filter);
  169.   /* CIF filter */
  170.   filter = gtk_file_filter_new ();
  171.   gtk_file_filter_set_name (filter, _("YUV CIF sequence"));
  172.   gtk_file_filter_add_pattern (filter, "*.cif");
  173.   gtk_file_chooser_add_filter (chooser, filter);
  174.   /* QCIF filter */
  175.   filter = gtk_file_filter_new ();
  176.   gtk_file_filter_set_name (filter, _("YUV QCIF sequence"));
  177.   gtk_file_filter_add_pattern (filter, "*.qcif");
  178.   gtk_file_chooser_add_filter (chooser, filter);
  179.   /* YUV4MPEG2 filter */
  180.   filter = gtk_file_filter_new ();
  181.   gtk_file_filter_set_name (filter, _("YUV4MPEG2 sequence"));
  182.   gtk_file_filter_add_pattern (filter, "*.y4m");
  183.   gtk_file_chooser_add_filter (chooser, filter);
  184. #ifdef AVIS_INPUT
  185.   /* AVI filter */
  186.   filter = gtk_file_filter_new ();
  187.   gtk_file_filter_set_name (filter, "AVI");
  188.   gtk_file_filter_add_pattern (filter, "*.avi");
  189.   gtk_file_chooser_add_filter (chooser, filter);
  190.   /* AVS filter */
  191.   filter = gtk_file_filter_new ();
  192.   gtk_file_filter_set_name (filter, _("Avisynth Script"));
  193.   gtk_file_filter_add_pattern (filter, "*.avs");
  194.   gtk_file_chooser_add_filter (chooser, filter);
  195. #endif
  196.   g_signal_connect_after(G_OBJECT (chooser), "response",
  197.                          G_CALLBACK (x264_chooser_window_cb),
  198.                          encode);
  199.   encode->file_input = gtk_file_chooser_button_new_with_dialog (GTK_WIDGET(chooser));
  200.   gtk_table_attach_defaults (GTK_TABLE (table), encode->file_input, 1, 2, 0, 1);
  201.   gtk_widget_show (encode->file_input);
  202.   label = gtk_label_new (_("Width:"));
  203.   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  204.   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
  205.   gtk_widget_show (label);
  206.   encode->width = gtk_entry_new_with_max_length (255);
  207.   gtk_entry_set_text (GTK_ENTRY (encode->width), "352");
  208.   g_signal_connect_after(G_OBJECT (encode->width), "changed",
  209.                    G_CALLBACK (x264_dimension_entry_cb),
  210.                    encode);
  211.   gtk_table_attach_defaults (GTK_TABLE (table), encode->width, 1, 2, 1, 2);
  212.   gtk_widget_show (encode->width);
  213.   label = gtk_label_new (_("Height:"));
  214.   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  215.   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3);
  216.   gtk_widget_show (label);
  217.   encode->height = gtk_entry_new_with_max_length (255);
  218.   gtk_entry_set_text (GTK_ENTRY (encode->height), "288");
  219.   gtk_table_attach_defaults (GTK_TABLE (table), encode->height, 1, 2, 2, 3);
  220.   g_signal_connect_after(G_OBJECT (encode->height), "changed",
  221.                    G_CALLBACK (x264_dimension_entry_cb),
  222.                    encode);
  223.   gtk_widget_show (encode->height);
  224.   label = gtk_label_new (_("Frame rate num:"));
  225.   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  226.   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 3, 4);
  227.   gtk_widget_show (label);
  228.   encode->fps_num = gtk_entry_new_with_max_length (255);
  229.   gtk_entry_set_text (GTK_ENTRY (encode->fps_num), "25");
  230.   gtk_table_attach_defaults (GTK_TABLE (table), encode->fps_num, 1, 2, 3, 4);
  231.   gtk_widget_show (encode->fps_num);
  232.   label = gtk_label_new (_("Frame rate den:"));
  233.   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  234.   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 4, 5);
  235.   gtk_widget_show (label);
  236.   encode->fps_den = gtk_entry_new_with_max_length (255);
  237.   gtk_entry_set_text (GTK_ENTRY (encode->fps_den), "1");
  238.   gtk_table_attach_defaults (GTK_TABLE (table), encode->fps_den, 1, 2, 4, 5);
  239.   gtk_widget_show (encode->fps_den);
  240.   label = gtk_label_new (_("Frame count:"));
  241.   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  242.   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
  243.   gtk_widget_show (label);
  244.   encode->frame_count = gtk_entry_new_with_max_length (255);
  245.   gtk_entry_set_text (GTK_ENTRY (encode->frame_count), "0");
  246.   gtk_table_attach_defaults (GTK_TABLE (table), encode->frame_count, 1, 2, 5, 6);
  247.   gtk_widget_show (encode->frame_count);
  248.   /* output */
  249.   frame = gtk_frame_new (_("Output file"));
  250.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame, FALSE, TRUE, 6);
  251.   gtk_widget_show (frame);
  252.   table = gtk_table_new (3, 2, TRUE);
  253.   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
  254.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  255.   gtk_container_set_border_width (GTK_CONTAINER (table), 6);
  256.   gtk_container_add (GTK_CONTAINER (frame), table);
  257.   gtk_widget_show (table);
  258.   label = gtk_label_new (_("Output path:"));
  259.   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  260.   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
  261.   gtk_widget_show (label);
  262.   encode->path_output = gtk_file_chooser_button_new (_("Select a path"),
  263.                                                      GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
  264.   gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (encode->path_output),
  265.                                        g_get_home_dir ());
  266.   gtk_table_attach_defaults (GTK_TABLE (table), encode->path_output, 1, 2, 0, 1);
  267.   gtk_widget_show (encode->path_output);
  268.   label = gtk_label_new (_("Output file (without ext.):"));
  269.   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  270.   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
  271.   gtk_widget_show (label);
  272.   encode->file_output = gtk_entry_new_with_max_length (4095);
  273.   gtk_table_attach_defaults (GTK_TABLE (table), encode->file_output, 1, 2, 1, 2);
  274.   gtk_widget_show (encode->file_output);
  275.   label = gtk_label_new (_("Container:"));
  276.   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  277.   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3);
  278.   gtk_widget_show (label);
  279.   encode->combo = gtk_combo_box_new_text ();
  280.   gtk_combo_box_append_text (GTK_COMBO_BOX (encode->combo),
  281.                              "Raw ES");
  282.   gtk_combo_box_append_text (GTK_COMBO_BOX (encode->combo),
  283.                              "Matroska");
  284. #ifdef MP4_OUTPUT
  285.   gtk_combo_box_append_text (GTK_COMBO_BOX (encode->combo),
  286.                              "Mp4");
  287. #endif
  288.   gtk_table_attach_defaults (GTK_TABLE (table), encode->combo, 1, 2, 2, 3);
  289.   gtk_widget_show (encode->combo);
  290.   gtk_combo_box_set_active (GTK_COMBO_BOX (encode->combo), 0);
  291.   gtk_widget_show (dialog);
  292. }
  293. /* Callbacks */
  294. static void
  295. x264_encode_shutdown (X264_Gtk_Encode *encode)
  296. {
  297.   if (!encode) return;
  298.   g_free (encode);
  299.   encode = NULL;
  300. }
  301. static gboolean
  302. x264_delete_window_cb (GtkWidget *widget UNUSED,
  303.                    GdkEvent  *event UNUSED,
  304.                    gpointer   user_data)
  305. {
  306.   gtk_main_quit ();
  307.   x264_encode_shutdown ((X264_Gtk_Encode *)user_data);
  308.   return TRUE;
  309. }
  310. static void
  311. x264_chooser_window_cb (GtkDialog *dialog,
  312.                     gint       res,
  313.                     gpointer   user_data)
  314. {
  315.   X264_Gtk_Encode *encode;
  316.   gboolean         sensitivity = TRUE;
  317.   x264_param_t     param;
  318.   hnd_t            hin;
  319.   char            *in;
  320. #define       BUFFER_LENGTH  64
  321.   gchar            buffer[BUFFER_LENGTH];
  322.   /* input interface */
  323.   int              (*p_open_infile)( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param );
  324.   int              (*p_get_frame_total)( hnd_t handle );
  325.   int              (*p_close_infile)( hnd_t handle );
  326.   encode = (X264_Gtk_Encode *)user_data;
  327.   in = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (encode->file_input));
  328.   if (!in) return;
  329.   /* Set defaults */
  330.   p_open_infile = open_file_yuv;
  331.   p_get_frame_total = get_frame_total_yuv;
  332.   p_close_infile = close_file_yuv;
  333.   param.i_width = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->width)), NULL));
  334.   param.i_height = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->height)), NULL));
  335.   param.i_fps_num = 25;
  336.   param.i_fps_den = 1;
  337.   param.i_frame_total = 0;
  338.   switch (res) {
  339.   case GTK_RESPONSE_OK:
  340.   case GTK_RESPONSE_ACCEPT:
  341.   case GTK_RESPONSE_APPLY: {
  342.     X264_Gtk_Encode  *encode = (X264_Gtk_Encode *)user_data;
  343.     GSList           *filters;
  344.     GtkFileFilter    *selected;
  345.     int               container;
  346.     filters = gtk_file_chooser_list_filters(GTK_FILE_CHOOSER (encode->file_input));
  347.     selected = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER (encode->file_input));
  348.     container = g_slist_index(filters, selected);
  349.     g_slist_free (filters);
  350.     if (container == 0)
  351.     {
  352.       /* All format needed, search for extension */
  353.       const char *ext = strrchr(in, '.');
  354.       if (!strncasecmp(ext, ".y4m", 4))
  355.         encode->container = X264_DEMUXER_Y4M;
  356.       else if (!strncasecmp(ext, ".avs", 4))
  357.         encode->container = X264_DEMUXER_AVS;
  358.       else if (!strncasecmp(ext, ".avi", 4))
  359.         encode->container = X264_DEMUXER_AVI;
  360.       else if (!strncasecmp(ext, ".cif", 4))
  361.         encode->container = X264_DEMUXER_CIF;
  362.       else if (!strncasecmp(ext, ".qcif", 4))
  363.         encode->container = X264_DEMUXER_QCIF;
  364.       else
  365.         encode->container = X264_DEMUXER_YUV;
  366.     }
  367.     else
  368.     {
  369.       /* The all supproted type is 0 => shift of 1 */
  370.       encode->container = (X264_Demuxer_Type)container-1;
  371.     }
  372.     switch (encode->container) {
  373.     case X264_DEMUXER_YUV: /* YUV */
  374.       break;
  375.     case X264_DEMUXER_CIF: /* YUV CIF */
  376.       param.i_width = 352;
  377.       param.i_height = 288;
  378.       break;
  379.     case X264_DEMUXER_QCIF: /* YUV QCIF */
  380.       /*   Default input file driver */
  381.       param.i_width = 176;
  382.       param.i_height = 144;
  383.       break;
  384.     case X264_DEMUXER_Y4M: /* YUV4MPEG */
  385.       /*   Default input file driver */
  386.       sensitivity = FALSE;
  387.       p_open_infile = open_file_y4m;
  388.       p_get_frame_total = get_frame_total_y4m;
  389.       p_close_infile = close_file_y4m;
  390.       break;
  391. #ifdef AVIS_INPUT
  392.     case X264_DEMUXER_AVI: /* AVI */
  393.     case X264_DEMUXER_AVS: /* AVS */
  394.       sensitivity = FALSE;
  395.       p_open_infile = open_file_avis;
  396.       p_get_frame_total = get_frame_total_avis;
  397.       p_close_infile = close_file_avis;
  398.     break;
  399. #endif
  400.     default: /* Unknown */
  401.       break;
  402.     }
  403.     break;
  404.   }
  405.   default:
  406.     break;
  407.   }
  408.   /* Modify dialog */
  409.   gtk_widget_set_sensitive(encode->width, sensitivity);
  410.   gtk_widget_set_sensitive(encode->height, sensitivity);
  411.   gtk_widget_set_sensitive(encode->fps_num, sensitivity);
  412.   gtk_widget_set_sensitive(encode->fps_den, sensitivity);
  413.   gtk_widget_set_sensitive(encode->frame_count, sensitivity);
  414.   /* Inquire input format */
  415.   if (param.i_width < 2) param.i_width = 352;
  416.   if (param.i_height < 2) param.i_height = 288;
  417.   if (p_open_infile (in, &hin, &param) >= 0) {
  418.     param.i_frame_total = p_get_frame_total(hin);
  419.     p_close_infile (hin);
  420.   } else {
  421.     GtkWidget *dialog_message;
  422.     dialog_message = gtk_message_dialog_new (GTK_WINDOW (dialog),
  423.                                              GTK_DIALOG_DESTROY_WITH_PARENT,
  424.                                              GTK_MESSAGE_ERROR,
  425.                                              GTK_BUTTONS_CLOSE,
  426.                                              strerror(errno));
  427.     gtk_dialog_run (GTK_DIALOG (dialog_message));
  428.     gtk_widget_destroy (dialog_message);
  429.   }
  430.   encode->size = x264_file_size(in);
  431.   if (g_snprintf(buffer, BUFFER_LENGTH, "%i", param.i_width) > 0)
  432.     gtk_entry_set_text (GTK_ENTRY (encode->width), buffer);
  433.   if (g_snprintf(buffer, BUFFER_LENGTH, "%i", param.i_height) > 0)
  434.     gtk_entry_set_text (GTK_ENTRY (encode->height), buffer);
  435.   if (g_snprintf(buffer, BUFFER_LENGTH, "%i", param.i_fps_num) > 0)
  436.     gtk_entry_set_text (GTK_ENTRY (encode->fps_num), buffer);
  437.   if (g_snprintf(buffer, BUFFER_LENGTH, "%i", param.i_fps_den) > 0)
  438.     gtk_entry_set_text (GTK_ENTRY (encode->fps_den), buffer);
  439.   if (g_snprintf(buffer, BUFFER_LENGTH, "%i", param.i_frame_total) > 0)
  440.     gtk_entry_set_text (GTK_ENTRY (encode->frame_count), buffer);
  441. }
  442. static void
  443. x264_dimension_entry_cb (GtkEditable *editable,
  444.                      gpointer     user_data)
  445. {
  446.   X264_Gtk_Encode *encode = (X264_Gtk_Encode *)user_data;
  447.   char             buffer[32];
  448.   gint             width;
  449.   gint             height;
  450.   gint             frame_size;
  451.   width = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->width)), NULL));
  452.   height = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->height)), NULL));
  453.   frame_size = (3*width*height)/2;
  454.   if (frame_size > 0 && encode->container <= X264_DEMUXER_QCIF)
  455.   {
  456.     snprintf(buffer, 32, "%lu", (long unsigned int)((encode->size+frame_size/2)/frame_size));
  457.     gtk_entry_set_text (GTK_ENTRY (encode->frame_count), buffer);
  458.   }
  459. }
  460. static void
  461. x264_configure_window_cb (GtkButton *button UNUSED,
  462.                       gpointer   user_data)
  463. {
  464.   GtkWidget *window;
  465.   window = x264_gtk_window_create (GTK_WIDGET (user_data));
  466.   x264_gtk_shutdown (window);
  467. }
  468. static void
  469. x264_response_window_cb (GtkDialog *dialog,
  470.                      gint       res,
  471.                      gpointer   user_data)
  472. {
  473.   switch (res) {
  474.   case GTK_RESPONSE_APPLY: {
  475.     x264_param_t     *param;
  476.     X264_Gtk         *x264_gtk;
  477.     X264_Gtk_Encode  *encode;
  478.     X264_Thread_Data *thread_data;
  479.     GtkWidget        *win_status;
  480.     GThread          *thread;
  481.     const gchar      *file_input = NULL;
  482.     const gchar      *path_output = NULL;
  483.     const gchar      *filename_output = NULL;
  484.     gchar            *file_output = NULL;
  485.     gchar            *ext;
  486.     gint              fds[2];
  487.     gint              out_container;
  488.     encode = (X264_Gtk_Encode *)user_data;
  489.     file_input = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (encode->file_input));
  490.     path_output = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (encode->path_output));
  491.     filename_output = gtk_entry_get_text (GTK_ENTRY (encode->file_output));
  492.     if (!file_input ||
  493.         (file_input[0] == '')) {
  494.       GtkWidget *dialog_message;
  495.       dialog_message = gtk_message_dialog_new (GTK_WINDOW (dialog),
  496.                                                GTK_DIALOG_DESTROY_WITH_PARENT,
  497.                                                GTK_MESSAGE_ERROR,
  498.                                                GTK_BUTTONS_CLOSE,
  499.                                                _("Error: input file name is not set"));
  500.       gtk_dialog_run (GTK_DIALOG (dialog_message));
  501.       gtk_widget_destroy (dialog_message);
  502.       break;
  503.     }
  504.     if (!filename_output ||
  505.         (filename_output[0] == '')) {
  506.       GtkWidget *dialog_message;
  507.       dialog_message = gtk_message_dialog_new (GTK_WINDOW (dialog),
  508.                                                GTK_DIALOG_DESTROY_WITH_PARENT,
  509.                                                GTK_MESSAGE_ERROR,
  510.                                                GTK_BUTTONS_CLOSE,
  511.                                                _("Error: output file name is not set"));
  512.       gtk_dialog_run (GTK_DIALOG (dialog_message));
  513.       gtk_widget_destroy (dialog_message);
  514.       break;
  515.     }
  516.     out_container = gtk_combo_box_get_active (GTK_COMBO_BOX (encode->combo));
  517.     switch (out_container) {
  518.     case 1:
  519.       ext = ".mkv";
  520.       break;
  521. #ifdef MP4_OUTPUT
  522.     case 2:
  523.       ext = ".mp4";
  524.       break;
  525. #endif
  526.     case 0:
  527.     default:
  528.       ext = ".264";
  529.     }
  530.     file_output = g_strconcat (path_output, "/", filename_output, ext, NULL);
  531.     g_print (_("file output : %sn"), file_output);
  532.     {
  533.       GIOChannel *file;
  534.       file = g_io_channel_new_file (file_output, "r", NULL);
  535.       if (file) {
  536.         GtkWidget   *dialog_overwrite;
  537.         GtkWidget   *eb;
  538.         GtkWidget   *label;
  539.         const gchar *label_text = NULL;
  540.         gint         res;
  541.         dialog_overwrite = gtk_dialog_new_with_buttons (_("Existing file"),
  542.                                                         GTK_WINDOW (dialog),
  543.                                                         GTK_DIALOG_DESTROY_WITH_PARENT,
  544.                                                         GTK_STOCK_YES,
  545.                                                         GTK_RESPONSE_ACCEPT,
  546.                                                         GTK_STOCK_NO,
  547.                                                         GTK_RESPONSE_REJECT,
  548.                                                         NULL);
  549.         eb = gtk_event_box_new ();
  550.         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog_overwrite)->vbox), eb);
  551.         gtk_container_set_border_width (GTK_CONTAINER (eb), 6);
  552.         gtk_widget_show (eb);
  553.         label_text = g_strconcat (_("Do you want to overwrite filen"),
  554.                                   file_output, " ?", NULL);
  555.         label = gtk_label_new (label_text);
  556.         gtk_container_add (GTK_CONTAINER (eb), label);
  557.         gtk_widget_show (label);
  558.         res = gtk_dialog_run (GTK_DIALOG (dialog_overwrite));
  559.         gtk_widget_destroy (dialog_overwrite);
  560.         g_io_channel_unref (file);
  561.         if ((res == GTK_RESPONSE_REJECT) || (res == GTK_RESPONSE_DELETE_EVENT))
  562.           break;
  563.       }
  564.     }
  565.     x264_gtk = x264_gtk_load ();
  566.     param = x264_gtk_param_get (x264_gtk);
  567.     x264_gtk_free (x264_gtk);
  568.     {
  569.       gint width;
  570.       gint height;
  571.       gint fps_num;
  572.       gint fps_den;
  573.       gint frame_count;
  574.       width = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->width)), NULL));
  575.       height = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->height)), NULL));
  576.       fps_num = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->fps_num)), NULL));
  577.       fps_den = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->fps_den)), NULL));
  578.       frame_count = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->frame_count)), NULL));
  579.       if ((width <= 0) ||
  580.           (height <= 0) ||
  581.           (fps_num <= 0) ||
  582.           (fps_den <= 0) ||
  583.           (frame_count < 0))
  584.         break;
  585.       param->i_width = width;
  586.       param->i_height = height;
  587.       param->i_fps_num = fps_num;
  588.       param->i_fps_den = fps_den;
  589.       param->i_frame_total = frame_count;
  590.     }
  591.     if (pipe (fds) == -1)
  592.       break;
  593.     thread_data = (X264_Thread_Data *)g_malloc0 (sizeof (X264_Thread_Data));
  594.     thread_data->param = param;
  595.     thread_data->file_input = g_strdup (file_input);
  596.     thread_data->file_output = g_strdup (file_output);
  597.     thread_data->in_container = encode->container;
  598.     thread_data->out_container = out_container;
  599.     g_free (file_output);
  600.     thread_data->io_read = g_io_channel_unix_new (fds[0]);
  601.     g_io_channel_set_encoding (thread_data->io_read, NULL, NULL);
  602.     thread_data->io_write = g_io_channel_unix_new (fds[1]);
  603.     g_io_channel_set_encoding (thread_data->io_write, NULL, NULL);
  604.     g_io_add_watch (thread_data->io_read, G_IO_IN,
  605.                     (GIOFunc)x264_fill_status_window, thread_data);
  606.     win_status = x264_gtk_encode_status_window (thread_data);
  607.     gtk_window_set_transient_for (GTK_WINDOW (win_status), GTK_WINDOW (dialog));
  608.     gtk_window_set_modal (GTK_WINDOW (win_status), TRUE);
  609.     gtk_widget_show (win_status);
  610.     //gtk_widget_hide(thread_data->end_button);
  611.     thread = g_thread_create ((GThreadFunc)x264_gtk_encode_encode, thread_data, FALSE, NULL);
  612.     break;
  613.   }
  614.   case GTK_RESPONSE_CLOSE:
  615.   default:
  616.     gtk_main_quit ();
  617.     x264_encode_shutdown ((X264_Gtk_Encode *)user_data);
  618.   }
  619. }
  620. static gboolean
  621. x264_fill_status_window (GIOChannel  *io UNUSED,
  622.                      GIOCondition condition UNUSED,
  623.                      gpointer     user_data)
  624. {
  625.   gchar             str[128];
  626.   X264_Thread_Data *thread_data;
  627.   X264_Pipe_Data    pipe_data;
  628.   GIOStatus         status;
  629.   gsize             size;
  630.   gint              eta;
  631.   gdouble           progress;
  632.   gdouble           fps;
  633.   thread_data = (X264_Thread_Data *)user_data;
  634.   status = g_io_channel_read_chars (thread_data->io_read,
  635.                                     (gchar *)&pipe_data,
  636.                                     sizeof (X264_Pipe_Data),
  637.                                     &size, NULL);
  638.   if (status != G_IO_STATUS_NORMAL) {
  639.     g_print (_("Error ! %d %d %dn"), status, (int)sizeof (X264_Pipe_Data), (int)size);
  640.     return FALSE;
  641.   }
  642.   snprintf (str, 128, "%d/%d", pipe_data.frame, pipe_data.frame_total);
  643.   gtk_entry_set_text (GTK_ENTRY (thread_data->current_video_frame),
  644.                       str);
  645.   snprintf (str, 128, _("%dKB"),
  646.             pipe_data.file >> 10);
  647.   gtk_entry_set_text (GTK_ENTRY (thread_data->video_data),
  648.                       str);
  649.   fps = pipe_data.elapsed > 0 ? 1000000.0 * (gdouble)pipe_data.frame / (gdouble)pipe_data.elapsed : 0.0;
  650.   snprintf (str, 128, _("%.2fKB/s (%.2f fps)"),
  651.             (double) pipe_data.file * 8 * thread_data->param->i_fps_num /
  652.             ((double) thread_data->param->i_fps_den * pipe_data.frame * 1000),
  653.             fps);
  654.   gtk_entry_set_text (GTK_ENTRY (thread_data->video_rendering_rate),
  655.                       str);
  656.   snprintf (str, 128, "%lld:%02lld:%02lld",
  657.             (pipe_data.elapsed / 1000000) / 3600,
  658.             ((pipe_data.elapsed / 1000000) / 60) % 60,
  659.             (pipe_data.elapsed / 1000000) % 60);
  660.   gtk_entry_set_text (GTK_ENTRY (thread_data->time_elapsed),
  661.                       str);
  662.   eta = pipe_data.elapsed * (pipe_data.frame_total - pipe_data.frame) / ((int64_t)pipe_data.frame * 1000000);
  663.   snprintf (str, 128, "%d:%02d:%02d", eta / 3600, (eta / 60) % 60, eta % 60);
  664.   gtk_entry_set_text (GTK_ENTRY (thread_data->time_remaining),
  665.                       str);
  666.   progress = (gdouble)pipe_data.frame / (gdouble)pipe_data.frame_total;
  667.   gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (thread_data->progress),
  668.                                  progress);
  669.   snprintf (str, 128, "%0.1f%%", 100.0 * progress);
  670.   gtk_progress_bar_set_text (GTK_PROGRESS_BAR (thread_data->progress), str);
  671.   return TRUE;
  672. }