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

Audio

开发平台:

Visual C++

  1. /*****************************************************************************
  2.  * x264_gtk_cqm.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 <gtk/gtk.h>
  26. #include "../x264.h"
  27. #include "x264_gtk_private.h"
  28. #include "x264_gtk_i18n.h"
  29. #include "x264_gtk_enum.h"
  30. /* Callbacks */
  31. static void x264_cqm_flat_matrix_cb   (GtkToggleButton *togglebutton,
  32.                                    gpointer         user_data);
  33. static void x264_cqm_jvt_matrix_cb    (GtkToggleButton *togglebutton,
  34.                                    gpointer         user_data);
  35. static void x264_cqm_custom_matrix_cb (GtkToggleButton *togglebutton,
  36.                                    gpointer         user_data);
  37. static void x264_cqm_matrix_file_cb   (GtkFileChooser  *filechooser,
  38.                                    gint             response,
  39.                                    gpointer         user_data);
  40. static GtkWidget *x264_cqm_4x4_page    (X264_Gui_Config *gconfig);
  41. static GtkWidget *x264_cqm_8x8_iy_page (X264_Gui_Config *gconfig);
  42. static GtkWidget *x264_cqm_8x8_py_page (X264_Gui_Config *gconfig);
  43. GtkWidget *
  44. x264_cqm_page (X264_Gui_Config *gconfig)
  45. {
  46.   GtkWidget   *vbox;
  47.   GtkWidget   *table;
  48.   GtkWidget   *notebook;
  49.   GtkWidget   *chooser;
  50.   GtkWidget   *label;
  51.   GtkWidget   *page;
  52.   GtkTooltips *tooltips;
  53.   tooltips = gtk_tooltips_new ();
  54.   vbox = gtk_vbox_new (FALSE, 0);
  55.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
  56.   table = gtk_table_new (4, 2, FALSE);
  57.   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
  58.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  59.   gtk_container_set_border_width (GTK_CONTAINER (table), 6);
  60.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 6);
  61.   gtk_widget_show (table);
  62.   gconfig->cqm.radio_flat = gtk_radio_button_new_with_label (NULL, _("Flat matrix"));
  63.   gtk_tooltips_set_tip (tooltips, gconfig->cqm.radio_flat,
  64.                         _("Flat matrix - description"),
  65.                         "");
  66.   gtk_table_attach_defaults (GTK_TABLE (table), gconfig->cqm.radio_flat,
  67.                              0, 1, 0, 1);
  68.   g_signal_connect (G_OBJECT (gconfig->cqm.radio_flat), "toggled",
  69.                     G_CALLBACK (x264_cqm_flat_matrix_cb), gconfig);
  70.   gtk_widget_show (gconfig->cqm.radio_flat);
  71.   gconfig->cqm.radio_jvt = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (gconfig->cqm.radio_flat), _("JVT matrix"));
  72.   gtk_tooltips_set_tip (tooltips, gconfig->cqm.radio_jvt,
  73.                         _("JVT matrix - description"),
  74.                         "");
  75.   gtk_table_attach_defaults (GTK_TABLE (table), gconfig->cqm.radio_jvt,
  76.                              0, 1, 1, 2);
  77.   g_signal_connect (G_OBJECT (gconfig->cqm.radio_jvt), "toggled",
  78.                     G_CALLBACK (x264_cqm_jvt_matrix_cb), gconfig);
  79.   gtk_widget_show (gconfig->cqm.radio_jvt);
  80.   gconfig->cqm.radio_custom = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (gconfig->cqm.radio_flat), _("Custom matrix"));
  81.   gtk_tooltips_set_tip (tooltips, gconfig->cqm.radio_custom,
  82.                         _("Custom matrix - description"),
  83.                         "");
  84.   gtk_table_attach_defaults (GTK_TABLE (table), gconfig->cqm.radio_custom,
  85.                              0, 1, 2, 3);
  86.   g_signal_connect (G_OBJECT (gconfig->cqm.radio_custom), "toggled",
  87.                     G_CALLBACK (x264_cqm_custom_matrix_cb), gconfig);
  88.   gtk_widget_show (gconfig->cqm.radio_custom);
  89.   chooser = gtk_file_chooser_dialog_new(_("Select a file"),
  90.                                         NULL,
  91.                                         GTK_FILE_CHOOSER_ACTION_OPEN,
  92.                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
  93.                                         GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
  94.                                         NULL);
  95.   g_signal_connect (G_OBJECT (chooser), "response",
  96.                     G_CALLBACK (x264_cqm_matrix_file_cb), gconfig);
  97.   gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser),
  98.                                        g_get_home_dir ());
  99.   gconfig->cqm.cqm_file = gtk_file_chooser_button_new_with_dialog (chooser);
  100.   gtk_table_attach_defaults (GTK_TABLE (table), gconfig->cqm.cqm_file,
  101.                              1, 2, 2, 3);
  102.   gtk_widget_show (gconfig->cqm.cqm_file);
  103.   notebook = gtk_notebook_new ();
  104.   gtk_table_attach_defaults (GTK_TABLE (table), notebook,
  105.                              0, 2, 3, 4);
  106.   gtk_widget_show (notebook);
  107.   label = gtk_label_new (_("4x4 quant. matrices"));
  108.   gtk_widget_show (label);
  109.   page = x264_cqm_4x4_page (gconfig);
  110.   gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, label);
  111.   gtk_widget_show (page);
  112.   label = gtk_label_new (_("8x8 I luma quant. matrices"));
  113.   gtk_widget_show (label);
  114.   page = x264_cqm_8x8_iy_page (gconfig);
  115.   gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, label);
  116.   gtk_widget_show (page);
  117.   label = gtk_label_new (_("8x8 P luma quant. matrices"));
  118.   gtk_widget_show (label);
  119.   page = x264_cqm_8x8_py_page (gconfig);
  120.   gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, label);
  121.   gtk_widget_show (page);
  122.   return vbox;
  123. }
  124. static GtkWidget *
  125. x264_cqm_4x4_page   (X264_Gui_Config *gconfig)
  126. {
  127.   GtkWidget     *table;
  128.   GtkWidget     *misc;
  129.   GtkWidget     *frame;
  130.   GtkWidget     *t;
  131.   GtkRequisition size;
  132.   gint           i;
  133.   misc = gtk_entry_new_with_max_length (3);
  134.   gtk_widget_size_request (misc, &size);
  135.   table = gtk_table_new (2, 2, FALSE);
  136.   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
  137.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  138.   gtk_container_set_border_width (GTK_CONTAINER (table), 6);
  139.   frame = gtk_frame_new (_("4x4 I luma quant. matrices"));
  140.   gtk_table_attach_defaults (GTK_TABLE (table), frame,
  141.                              0, 1, 0, 1);
  142.   gtk_widget_show (frame);
  143.   t = gtk_table_new (4, 4, FALSE);
  144.   gtk_table_set_row_spacings (GTK_TABLE (t), 6);
  145.   gtk_table_set_col_spacings (GTK_TABLE (t), 6);
  146.   gtk_container_set_border_width (GTK_CONTAINER (t), 6);
  147.   gtk_container_add (GTK_CONTAINER (frame), t);
  148.   gtk_widget_show (t);
  149.   for (i = 0; i < 16; i++) {
  150.     gconfig->cqm.cqm_4iy[i] = gtk_entry_new_with_max_length (3);
  151.     gtk_widget_set_size_request (gconfig->cqm.cqm_4iy[i], 25, size.height);
  152.     gtk_table_attach_defaults (GTK_TABLE (t), gconfig->cqm.cqm_4iy[i],
  153.                                i >> 2, (i >> 2) + 1, i & 3, (i & 3) + 1);
  154.     gtk_widget_show (gconfig->cqm.cqm_4iy[i]);
  155.   }
  156.   frame = gtk_frame_new (_("4x4 I chroma quant. matrices"));
  157.   gtk_table_attach_defaults (GTK_TABLE (table), frame,
  158.                              0, 1, 1, 2);
  159.   gtk_widget_show (frame);
  160.   t = gtk_table_new (4, 4, FALSE);
  161.   gtk_table_set_row_spacings (GTK_TABLE (t), 6);
  162.   gtk_table_set_col_spacings (GTK_TABLE (t), 6);
  163.   gtk_container_set_border_width (GTK_CONTAINER (t), 6);
  164.   gtk_container_add (GTK_CONTAINER (frame), t);
  165.   gtk_widget_show (t);
  166.   for (i = 0; i < 16; i++) {
  167.     gconfig->cqm.cqm_4ic[i] = gtk_entry_new_with_max_length (3);
  168.     gtk_widget_set_size_request (gconfig->cqm.cqm_4ic[i], 25, size.height);
  169.     gtk_table_attach_defaults (GTK_TABLE (t), gconfig->cqm.cqm_4ic[i],
  170.                                i >> 2, (i >> 2) + 1, i & 3, (i & 3) + 1);
  171.     gtk_widget_show (gconfig->cqm.cqm_4ic[i]);
  172.   }
  173.   frame = gtk_frame_new (_("4x4 P luma quant. matrix"));
  174.   gtk_table_attach_defaults (GTK_TABLE (table), frame,
  175.                              1, 2, 0, 1);
  176.   gtk_widget_show (frame);
  177.   t = gtk_table_new (4, 4, FALSE);
  178.   gtk_table_set_row_spacings (GTK_TABLE (t), 6);
  179.   gtk_table_set_col_spacings (GTK_TABLE (t), 6);
  180.   gtk_container_set_border_width (GTK_CONTAINER (t), 6);
  181.   gtk_container_add (GTK_CONTAINER (frame), t);
  182.   gtk_widget_show (t);
  183.   for (i = 0; i < 16; i++) {
  184.     gconfig->cqm.cqm_4py[i] = gtk_entry_new_with_max_length (3);
  185.     gtk_widget_set_size_request (gconfig->cqm.cqm_4py[i], 25, size.height);
  186.     gtk_table_attach_defaults (GTK_TABLE (t), gconfig->cqm.cqm_4py[i],
  187.                                i >> 2, (i >> 2) + 1, i & 3, (i & 3) + 1);
  188.     gtk_widget_show (gconfig->cqm.cqm_4py[i]);
  189.   }
  190.   frame = gtk_frame_new (_("4x4 P chroma quant. matrix"));
  191.   gtk_table_attach_defaults (GTK_TABLE (table), frame,
  192.                              1, 2, 1, 2);
  193.   gtk_widget_show (frame);
  194.   t = gtk_table_new (4, 4, FALSE);
  195.   gtk_table_set_row_spacings (GTK_TABLE (t), 6);
  196.   gtk_table_set_col_spacings (GTK_TABLE (t), 6);
  197.   gtk_container_set_border_width (GTK_CONTAINER (t), 6);
  198.   gtk_container_add (GTK_CONTAINER (frame), t);
  199.   gtk_widget_show (t);
  200.   for (i = 0; i < 16; i++) {
  201.     gconfig->cqm.cqm_4pc[i] = gtk_entry_new_with_max_length (3);
  202.     gtk_widget_set_size_request (gconfig->cqm.cqm_4pc[i], 25, size.height);
  203.     gtk_table_attach_defaults (GTK_TABLE (t), gconfig->cqm.cqm_4pc[i],
  204.                                i >> 2, (i >> 2) + 1, i & 3, (i & 3) + 1);
  205.     gtk_widget_show (gconfig->cqm.cqm_4pc[i]);
  206.   }
  207.   return table;
  208. }
  209. static GtkWidget *
  210. x264_cqm_8x8_iy_page (X264_Gui_Config *gconfig)
  211. {
  212.   GtkWidget     *table;
  213.   GtkWidget     *misc;
  214.   GtkRequisition size;
  215.   gint           i;
  216.   misc = gtk_entry_new_with_max_length (3);
  217.   gtk_widget_size_request (misc, &size);
  218.   table = gtk_table_new (8, 8, FALSE);
  219.   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
  220.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  221.   gtk_container_set_border_width (GTK_CONTAINER (table), 6);
  222.   for (i = 0; i < 64; i++) {
  223.     gconfig->cqm.cqm_8iy[i] = gtk_entry_new_with_max_length (3);
  224.     gtk_widget_set_size_request (gconfig->cqm.cqm_8iy[i], 25, size.height);
  225.     gtk_table_attach_defaults (GTK_TABLE (table), gconfig->cqm.cqm_8iy[i],
  226.                                i >> 3, (i >> 3) + 1, i & 7, (i & 7) + 1);
  227.     gtk_widget_show (gconfig->cqm.cqm_8iy[i]);
  228.   }
  229.   return table;
  230. }
  231. static GtkWidget *
  232. x264_cqm_8x8_py_page (X264_Gui_Config *gconfig)
  233. {
  234.   GtkWidget     *table;
  235.   GtkWidget     *misc;
  236.   GtkRequisition size;
  237.   gint           i;
  238.   misc = gtk_entry_new_with_max_length (3);
  239.   gtk_widget_size_request (misc, &size);
  240.   table = gtk_table_new (8, 8, FALSE);
  241.   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
  242.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  243.   gtk_container_set_border_width (GTK_CONTAINER (table), 6);
  244.   for (i = 0; i < 64; i++) {
  245.     gconfig->cqm.cqm_8py[i] = gtk_entry_new_with_max_length (3);
  246.     gtk_widget_set_size_request (gconfig->cqm.cqm_8py[i], 25, size.height);
  247.     gtk_table_attach_defaults (GTK_TABLE (table), gconfig->cqm.cqm_8py[i],
  248.                                i >> 3, (i >> 3) + 1, i & 7, (i & 7) + 1);
  249.     gtk_widget_show (gconfig->cqm.cqm_8py[i]);
  250.   }
  251.   return table;
  252. }
  253. /* Callbacks */
  254. static void
  255. x264_cqm_flat_matrix_cb (GtkToggleButton *togglebutton,
  256.                      gpointer         user_data)
  257. {
  258.   X264_Gui_Config *gconfig;
  259.   gconfig = (X264_Gui_Config *)user_data;
  260.   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->cqm.radio_flat))) {
  261.     gint i;
  262.     gtk_widget_set_sensitive (gconfig->cqm.cqm_file, FALSE);
  263.     for (i = 0; i < 16; i++) {
  264.       gtk_widget_set_sensitive (gconfig->cqm.cqm_4iy[i], FALSE);
  265.       gtk_widget_set_sensitive (gconfig->cqm.cqm_4ic[i], FALSE);
  266.       gtk_widget_set_sensitive (gconfig->cqm.cqm_4py[i], FALSE);
  267.       gtk_widget_set_sensitive (gconfig->cqm.cqm_4pc[i], FALSE);
  268.     }
  269.     for (i = 0; i < 64; i++) {
  270.       gtk_widget_set_sensitive (gconfig->cqm.cqm_8iy[i], FALSE);
  271.       gtk_widget_set_sensitive (gconfig->cqm.cqm_8py[i], FALSE);
  272.     }
  273.   }
  274. }
  275. static void
  276. x264_cqm_jvt_matrix_cb (GtkToggleButton *togglebutton,
  277.                     gpointer         user_data)
  278. {
  279.   X264_Gui_Config *gconfig;
  280.   gconfig = (X264_Gui_Config *)user_data;
  281.   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->cqm.radio_jvt))) {
  282.     gint i;
  283.     gtk_widget_set_sensitive (gconfig->cqm.cqm_file, FALSE);
  284.     for (i = 0; i < 16; i++) {
  285.       gtk_widget_set_sensitive (gconfig->cqm.cqm_4iy[i], FALSE);
  286.       gtk_widget_set_sensitive (gconfig->cqm.cqm_4ic[i], FALSE);
  287.       gtk_widget_set_sensitive (gconfig->cqm.cqm_4py[i], FALSE);
  288.       gtk_widget_set_sensitive (gconfig->cqm.cqm_4pc[i], FALSE);
  289.     }
  290.     for (i = 0; i < 64; i++) {
  291.       gtk_widget_set_sensitive (gconfig->cqm.cqm_8iy[i], FALSE);
  292.       gtk_widget_set_sensitive (gconfig->cqm.cqm_8py[i], FALSE);
  293.     }
  294.   }
  295. }
  296. static void
  297. x264_cqm_custom_matrix_cb (GtkToggleButton *togglebutton,
  298.                        gpointer         user_data)
  299. {
  300.   X264_Gui_Config *gconfig;
  301.   gconfig = (X264_Gui_Config *)user_data;
  302.   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gconfig->cqm.radio_custom))) {
  303.     gint i;
  304.     gtk_widget_set_sensitive (gconfig->cqm.cqm_file, TRUE);
  305.     for (i = 0; i < 16; i++) {
  306.       gtk_widget_set_sensitive (gconfig->cqm.cqm_4iy[i], TRUE);
  307.       gtk_widget_set_sensitive (gconfig->cqm.cqm_4ic[i], TRUE);
  308.       gtk_widget_set_sensitive (gconfig->cqm.cqm_4py[i], TRUE);
  309.       gtk_widget_set_sensitive (gconfig->cqm.cqm_4pc[i], TRUE);
  310.     }
  311.     for (i = 0; i < 64; i++) {
  312.       gtk_widget_set_sensitive (gconfig->cqm.cqm_8iy[i], TRUE);
  313.       gtk_widget_set_sensitive (gconfig->cqm.cqm_8py[i], TRUE);
  314.     }
  315.   }
  316. }
  317. static gboolean
  318. x264_set_coefs (int size, GtkWidget **entries, GIOChannel *file)
  319. {
  320.   gchar *line;
  321.   gsize  length;
  322.   int    i = 0;
  323.   int    offset = 0;
  324.   while (i < size) {
  325.     gchar **coefs;
  326.     int     j;
  327.     if (g_io_channel_read_line (file, &line, &length, NULL, NULL) != G_IO_STATUS_NORMAL) {
  328.       g_print ("Not a JM custom AVC matrix compliant filen");
  329.       return FALSE;
  330.     }
  331.     if ((line[0] == '') || (line[0] == 'n') || (line[0] == 'r') || (line[0] == '#')) {
  332.       g_free (line);
  333.       continue;
  334.     }
  335.     coefs = g_strsplit (line, ",", size + 1);
  336.     for (j = 0; j < size; j++) {
  337.       gtk_entry_set_text (GTK_ENTRY (entries[offset]), coefs[j]);
  338.       offset++;
  339.     }
  340.     g_strfreev (coefs);
  341.     g_free (line);
  342.     i++;
  343.   }
  344.   return TRUE;
  345. }
  346. static void
  347. x264_cqm_matrix_file_cb (GtkFileChooser  *filechooser,
  348.                      gint             response,
  349.                      gpointer         user_data)
  350. {
  351.   X264_Gui_Config *gconfig;
  352.   GIOChannel      *file;
  353.   GError          *error = NULL;
  354.   gchar           *filename;
  355.   gchar           *line;
  356.   gsize            length;
  357.   if (!user_data)
  358.     return;
  359.   gconfig = (X264_Gui_Config *)user_data;
  360.   filename = gtk_file_chooser_get_filename (filechooser);
  361.   file = g_io_channel_new_file (filename, "r", &error);
  362.   if (error) {
  363.     g_print ("Can not open file %sn", filename);
  364.     g_free (filename);
  365.     return;
  366.   }
  367.   while ((g_io_channel_read_line (file, &line, &length, NULL, NULL) == G_IO_STATUS_NORMAL)) {
  368.     if (!line) continue;
  369.     if ((line[0] == '') || (line[0] == 'n') || (line[0] == 'r') || (line[0] == '#')) {
  370.       g_free (line);
  371.       continue;
  372.     }
  373.     if (g_str_has_prefix (line, "INTRA4X4_LUMA")) {
  374.       g_free (line);
  375.       if (!x264_set_coefs (4, gconfig->cqm.cqm_4iy, file)) {
  376.         g_free (filename);
  377.         return;
  378.       }
  379.       continue;
  380.     }
  381.     if (g_str_has_prefix (line, "INTRA4X4_CHROMAU")) {
  382.       g_free (line);
  383.       if (!x264_set_coefs (4, gconfig->cqm.cqm_4ic, file)) {
  384.         g_free (filename);
  385.         return;
  386.       }
  387.       continue;
  388.     }
  389.     if (g_str_has_prefix (line, "INTER4X4_LUMA")) {
  390.       g_free (line);
  391.       if (!x264_set_coefs (4, gconfig->cqm.cqm_4py, file)) {
  392.         g_free (filename);
  393.         return;
  394.       }
  395.       continue;
  396.     }
  397.     if (g_str_has_prefix (line, "INTER4X4_CHROMAU")) {
  398.       g_free (line);
  399.       if (!x264_set_coefs (4, gconfig->cqm.cqm_4pc, file)) {
  400.         g_free (filename);
  401.         return;
  402.       }
  403.       continue;
  404.     }
  405.     if (g_str_has_prefix (line, "INTRA8X8_LUMA")) {
  406.       g_free (line);
  407.       if (!x264_set_coefs (8, gconfig->cqm.cqm_8iy, file)) {
  408.         g_free (filename);
  409.         return;
  410.       }
  411.       continue;
  412.     }
  413.     if (g_str_has_prefix (line, "INTER8X8_LUMA")) {
  414.       g_free (line);
  415.       if (!x264_set_coefs (8, gconfig->cqm.cqm_8py, file)) {
  416.         g_free (filename);
  417.         return;
  418.       }
  419.       continue;
  420.     }
  421.   }
  422.   g_free (filename);
  423. }