1 #if defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ || defined __DragonFly__
7 #ifdef _WIN32 /* Needed to define _O_BINARY */
9 # define strncasecmp _strnicmp
13 #include <sys/stat.h> /* For stat */
18 #include "../config.h"
19 #include "x264_icon.h"
21 #include "x264_gtk_demuxers.h"
22 #include "x264_gtk_encode_private.h"
23 #include "x264_gtk_encode_encode.h"
24 #include "x264_gtk_encode_status_window.h"
27 typedef struct X264_Gtk_Encode_ X264_Gtk_Encode;
29 struct X264_Gtk_Encode_
31 GtkWidget *main_dialog;
34 X264_Demuxer_Type container;
35 guint64 size; /* For YUV formats */
36 GtkWidget *file_input;
41 GtkWidget *frame_count;
44 GtkWidget *path_output;
45 GtkWidget *file_output;
51 static gboolean _delete_window_cb (GtkWidget *widget,
54 static void _configure_window_cb (GtkButton *button,
56 static void _chooser_window_cb (GtkDialog *dialog,
59 static void _response_window_cb (GtkDialog *dialog,
62 static void _dimension_entry_cb (GtkEditable *editable,
65 static gboolean _fill_status_window (GIOChannel *io,
66 GIOCondition condition,
70 _file_size(const char* name)
73 memset(&buf, 0, sizeof(struct stat));
75 if (stat(name, &buf) < 0)
77 fprintf(stderr, "Can't stat file\n");
84 x264_gtk_encode_main_window ()
91 GtkFileChooser *chooser;
92 GtkFileFilter *filter;
94 X264_Gtk_Encode *encode;
96 encode = (X264_Gtk_Encode *)g_malloc0 (sizeof (X264_Gtk_Encode));
98 dialog = gtk_dialog_new_with_buttons ("X264 Gtk Encoder",
101 icon = gdk_pixbuf_new_from_inline (-1, x264_icon,
103 gtk_window_set_icon (GTK_WINDOW (dialog), icon);
104 g_signal_connect (G_OBJECT (dialog),
106 G_CALLBACK (_delete_window_cb),
108 g_signal_connect (G_OBJECT (dialog),
110 G_CALLBACK (_response_window_cb),
112 encode->main_dialog = dialog;
114 button = gtk_button_new_with_label ("Configure");
115 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), button, FALSE, TRUE, 6);
116 g_signal_connect (G_OBJECT (button),
118 G_CALLBACK (_configure_window_cb),
120 gtk_widget_show (button);
122 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
123 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
124 GTK_STOCK_EXECUTE, GTK_RESPONSE_APPLY,
128 frame = gtk_frame_new ("Input file");
129 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame, FALSE, TRUE, 6);
130 gtk_widget_show (frame);
132 table = gtk_table_new (6, 2, TRUE);
133 gtk_table_set_row_spacings (GTK_TABLE (table), 6);
134 gtk_table_set_col_spacings (GTK_TABLE (table), 6);
135 gtk_container_set_border_width (GTK_CONTAINER (table), 6);
136 gtk_container_add (GTK_CONTAINER (frame), table);
137 gtk_widget_show (table);
139 label = gtk_label_new ("Input file:");
140 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
141 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
142 gtk_widget_show (label);
144 chooser = (GtkFileChooser*)
145 gtk_file_chooser_dialog_new("Select a file",
147 GTK_FILE_CHOOSER_ACTION_OPEN,
148 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
149 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
151 gtk_file_chooser_set_current_folder (chooser, g_get_home_dir ());
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");
160 gtk_file_filter_add_pattern (filter, "*.avs");
161 gtk_file_filter_add_pattern (filter, "*.avi");
163 gtk_file_chooser_add_filter (chooser, 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);
171 filter = gtk_file_filter_new ();
172 gtk_file_filter_set_name (filter, "YUV CIF sequence");
173 gtk_file_filter_add_pattern (filter, "*.cif");
174 gtk_file_chooser_add_filter (chooser, filter);
177 filter = gtk_file_filter_new ();
178 gtk_file_filter_set_name (filter, "YUV QCIF sequence");
179 gtk_file_filter_add_pattern (filter, "*.qcif");
180 gtk_file_chooser_add_filter (chooser, filter);
182 /* YUV4MPEG2 filter */
183 filter = gtk_file_filter_new ();
184 gtk_file_filter_set_name (filter, "YUV4MPEG2 sequence");
185 gtk_file_filter_add_pattern (filter, "*.y4m");
186 gtk_file_chooser_add_filter (chooser, filter);
190 filter = gtk_file_filter_new ();
191 gtk_file_filter_set_name (filter, "AVI");
192 gtk_file_filter_add_pattern (filter, "*.avi");
193 gtk_file_chooser_add_filter (chooser, filter);
195 filter = gtk_file_filter_new ();
196 gtk_file_filter_set_name (filter, "Avisynth Script");
197 gtk_file_filter_add_pattern (filter, "*.avs");
198 gtk_file_chooser_add_filter (chooser, filter);
200 g_signal_connect_after(G_OBJECT (chooser), "response",
201 G_CALLBACK (_chooser_window_cb),
203 encode->file_input = gtk_file_chooser_button_new_with_dialog(GTK_WIDGET(chooser));
204 gtk_table_attach_defaults (GTK_TABLE (table), encode->file_input, 1, 2, 0, 1);
205 gtk_widget_show (encode->file_input);
207 label = gtk_label_new ("Width:");
208 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
209 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
210 gtk_widget_show (label);
212 encode->width = gtk_entry_new_with_max_length (255);
213 gtk_entry_set_text (GTK_ENTRY (encode->width), "352");
214 g_signal_connect_after(G_OBJECT (encode->width), "changed",
215 G_CALLBACK (_dimension_entry_cb),
217 gtk_table_attach_defaults (GTK_TABLE (table), encode->width, 1, 2, 1, 2);
218 gtk_widget_show (encode->width);
220 label = gtk_label_new ("Height:");
221 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
222 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3);
223 gtk_widget_show (label);
225 encode->height = gtk_entry_new_with_max_length (255);
226 gtk_entry_set_text (GTK_ENTRY (encode->height), "288");
227 gtk_table_attach_defaults (GTK_TABLE (table), encode->height, 1, 2, 2, 3);
228 g_signal_connect_after(G_OBJECT (encode->height), "changed",
229 G_CALLBACK (_dimension_entry_cb),
231 gtk_widget_show (encode->height);
233 label = gtk_label_new ("Frame rate num:");
234 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
235 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 3, 4);
236 gtk_widget_show (label);
238 encode->fps_num = gtk_entry_new_with_max_length (255);
239 gtk_entry_set_text (GTK_ENTRY (encode->fps_num), "25");
240 gtk_table_attach_defaults (GTK_TABLE (table), encode->fps_num, 1, 2, 3, 4);
241 gtk_widget_show (encode->fps_num);
243 label = gtk_label_new ("Frame rate den:");
244 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
245 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 4, 5);
246 gtk_widget_show (label);
248 encode->fps_den = gtk_entry_new_with_max_length (255);
249 gtk_entry_set_text (GTK_ENTRY (encode->fps_den), "1");
250 gtk_table_attach_defaults (GTK_TABLE (table), encode->fps_den, 1, 2, 4, 5);
251 gtk_widget_show (encode->fps_den);
253 label = gtk_label_new ("Frame count:");
254 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
255 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
256 gtk_widget_show (label);
258 encode->frame_count = gtk_entry_new_with_max_length (255);
259 gtk_entry_set_text (GTK_ENTRY (encode->frame_count), "0");
260 gtk_table_attach_defaults (GTK_TABLE (table), encode->frame_count, 1, 2, 5, 6);
261 gtk_widget_show (encode->frame_count);
264 frame = gtk_frame_new ("Output file");
265 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame, FALSE, TRUE, 6);
266 gtk_widget_show (frame);
268 table = gtk_table_new (3, 2, TRUE);
269 gtk_table_set_row_spacings (GTK_TABLE (table), 6);
270 gtk_table_set_col_spacings (GTK_TABLE (table), 6);
271 gtk_container_set_border_width (GTK_CONTAINER (table), 6);
272 gtk_container_add (GTK_CONTAINER (frame), table);
273 gtk_widget_show (table);
275 label = gtk_label_new ("Output path:");
276 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
277 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
278 gtk_widget_show (label);
280 encode->path_output = gtk_file_chooser_button_new ("Select a path",
281 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
282 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (encode->path_output),
284 gtk_table_attach_defaults (GTK_TABLE (table), encode->path_output, 1, 2, 0, 1);
285 gtk_widget_show (encode->path_output);
287 label = gtk_label_new ("Output file (without ext.):");
288 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
289 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
290 gtk_widget_show (label);
292 encode->file_output = gtk_entry_new_with_max_length (4095);
293 gtk_table_attach_defaults (GTK_TABLE (table), encode->file_output, 1, 2, 1, 2);
294 gtk_widget_show (encode->file_output);
296 label = gtk_label_new ("Container:");
297 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
298 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3);
299 gtk_widget_show (label);
301 encode->combo = gtk_combo_box_new_text ();
302 gtk_combo_box_append_text (GTK_COMBO_BOX (encode->combo),
304 gtk_combo_box_append_text (GTK_COMBO_BOX (encode->combo),
307 gtk_combo_box_append_text (GTK_COMBO_BOX (encode->combo),
310 gtk_table_attach_defaults (GTK_TABLE (table), encode->combo, 1, 2, 2, 3);
311 gtk_widget_show (encode->combo);
313 gtk_combo_box_set_active (GTK_COMBO_BOX (encode->combo), 0);
315 gtk_widget_show (dialog);
321 _encode_shutdown (X264_Gtk_Encode *encode)
330 _delete_window_cb (GtkWidget *widget __UNUSED__,
331 GdkEvent *event __UNUSED__,
335 _encode_shutdown ((X264_Gtk_Encode *)user_data);
341 _chooser_window_cb (GtkDialog *dialog,
345 X264_Gtk_Encode *encode;
346 gboolean sensitivity = TRUE;
350 #define BUFFER_LENGTH 64
351 gchar buffer[BUFFER_LENGTH];
353 /* input interface */
354 int (*p_open_infile)( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param );
355 int (*p_get_frame_total)( hnd_t handle );
356 int (*p_close_infile)( hnd_t handle );
358 encode = (X264_Gtk_Encode *)user_data;
359 in = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (encode->file_input));
363 p_open_infile = open_file_yuv;
364 p_get_frame_total = get_frame_total_yuv;
365 p_close_infile = close_file_yuv;
366 param.i_width = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->width)), NULL));
367 param.i_height = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->height)), NULL));
368 param.i_fps_num = 25;
370 param.i_frame_total = 0;
373 case GTK_RESPONSE_OK:
374 case GTK_RESPONSE_ACCEPT:
375 case GTK_RESPONSE_APPLY: {
376 X264_Gtk_Encode *encode = (X264_Gtk_Encode *)user_data;
378 GtkFileFilter *selected;
381 filters = gtk_file_chooser_list_filters(GTK_FILE_CHOOSER (encode->file_input));
382 selected = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER (encode->file_input));
383 container = g_slist_index(filters, selected);
384 g_slist_free (filters);
388 /* All format needed, search for extension */
389 const char *ext = strrchr(in, '.');
390 if (!strncasecmp(ext, ".y4m", 4))
391 encode->container = X264_DEMUXER_Y4M;
392 else if (!strncasecmp(ext, ".avs", 4))
393 encode->container = X264_DEMUXER_AVS;
394 else if (!strncasecmp(ext, ".avi", 4))
395 encode->container = X264_DEMUXER_AVI;
396 else if (!strncasecmp(ext, ".cif", 4))
397 encode->container = X264_DEMUXER_CIF;
398 else if (!strncasecmp(ext, ".qcif", 4))
399 encode->container = X264_DEMUXER_QCIF;
401 encode->container = X264_DEMUXER_YUV;
405 /* The all supproted type is 0 => shift of 1 */
406 encode->container = (X264_Demuxer_Type)container-1;
409 switch (encode->container) {
410 case X264_DEMUXER_YUV: /* YUV */
412 case X264_DEMUXER_CIF: /* YUV CIF */
414 param.i_height = 288;
416 case X264_DEMUXER_QCIF: /* YUV QCIF */
417 /* Default input file driver */
419 param.i_height = 144;
421 case X264_DEMUXER_Y4M: /* YUV4MPEG */
422 /* Default input file driver */
424 p_open_infile = open_file_y4m;
425 p_get_frame_total = get_frame_total_y4m;
426 p_close_infile = close_file_y4m;
429 case X264_DEMUXER_AVI: /* AVI */
430 case X264_DEMUXER_AVS: /* AVS */
432 p_open_infile = open_file_avis;
433 p_get_frame_total = get_frame_total_avis;
434 p_close_infile = close_file_avis;
437 default: /* Unknown */
447 gtk_widget_set_sensitive(encode->width, sensitivity);
448 gtk_widget_set_sensitive(encode->height, sensitivity);
449 gtk_widget_set_sensitive(encode->fps_num, sensitivity);
450 gtk_widget_set_sensitive(encode->fps_den, sensitivity);
451 gtk_widget_set_sensitive(encode->frame_count, sensitivity);
453 /* Inquire input format */
454 if (param.i_width < 2) param.i_width = 352;
455 if (param.i_height < 2) param.i_height = 288;
456 if (p_open_infile (in, &hin, ¶m) >= 0) {
457 param.i_frame_total = p_get_frame_total(hin);
458 p_close_infile (hin);
460 GtkWidget *dialog_message;
462 dialog_message = gtk_message_dialog_new (GTK_WINDOW (dialog),
463 GTK_DIALOG_DESTROY_WITH_PARENT,
467 gtk_dialog_run (GTK_DIALOG (dialog_message));
468 gtk_widget_destroy (dialog_message);
470 encode->size = _file_size(in);
472 if (g_snprintf(buffer, BUFFER_LENGTH, "%i", param.i_width) > 0)
473 gtk_entry_set_text (GTK_ENTRY (encode->width), buffer);
474 if (g_snprintf(buffer, BUFFER_LENGTH, "%i", param.i_height) > 0)
475 gtk_entry_set_text (GTK_ENTRY (encode->height), buffer);
476 if (g_snprintf(buffer, BUFFER_LENGTH, "%i", param.i_fps_num) > 0)
477 gtk_entry_set_text (GTK_ENTRY (encode->fps_num), buffer);
478 if (g_snprintf(buffer, BUFFER_LENGTH, "%i", param.i_fps_den) > 0)
479 gtk_entry_set_text (GTK_ENTRY (encode->fps_den), buffer);
481 if (g_snprintf(buffer, BUFFER_LENGTH, "%i", param.i_frame_total) > 0)
482 gtk_entry_set_text (GTK_ENTRY (encode->frame_count), buffer);
485 _dimension_entry_cb (GtkEditable *editable,
488 X264_Gtk_Encode *encode = (X264_Gtk_Encode *)user_data;
494 width = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->width)), NULL));
495 height = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->height)), NULL));
496 frame_size = (3*width*height)/2;
498 if (frame_size > 0 && encode->container <= X264_DEMUXER_QCIF)
500 snprintf(buffer, 32, "%lu", (long unsigned int)((encode->size+frame_size/2)/frame_size));
501 gtk_entry_set_text (GTK_ENTRY (encode->frame_count), buffer);
506 _configure_window_cb (GtkButton *button __UNUSED__,
511 window = x264_gtk_window_create (GTK_WIDGET (user_data));
512 x264_gtk_shutdown (window);
516 _response_window_cb (GtkDialog *dialog,
521 case GTK_RESPONSE_APPLY: {
524 X264_Gtk_Encode *encode;
525 X264_Thread_Data *thread_data;
526 GtkWidget *win_status;
528 const gchar *file_input = NULL;
529 const gchar *path_output = NULL;
530 const gchar *filename_output = NULL;
531 gchar *file_output = NULL;
536 encode = (X264_Gtk_Encode *)user_data;
537 file_input = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (encode->file_input));
538 path_output = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (encode->path_output));
539 filename_output = gtk_entry_get_text (GTK_ENTRY (encode->file_output));
542 (file_input[0] == '\0')) {
543 GtkWidget *dialog_message;
545 dialog_message = gtk_message_dialog_new (GTK_WINDOW (dialog),
546 GTK_DIALOG_DESTROY_WITH_PARENT,
549 "Error: input file name is not set");
550 gtk_dialog_run (GTK_DIALOG (dialog_message));
551 gtk_widget_destroy (dialog_message);
555 if (!filename_output ||
556 (filename_output[0] == '\0')) {
557 GtkWidget *dialog_message;
559 dialog_message = gtk_message_dialog_new (GTK_WINDOW (dialog),
560 GTK_DIALOG_DESTROY_WITH_PARENT,
563 "Error: output file name is not set");
564 gtk_dialog_run (GTK_DIALOG (dialog_message));
565 gtk_widget_destroy (dialog_message);
569 out_container = gtk_combo_box_get_active (GTK_COMBO_BOX (encode->combo));
571 switch (out_container) {
585 file_output = g_strconcat (path_output, "/", filename_output, ext, NULL);
586 g_print ("file output : %s\n", file_output);
588 x264_gtk = x264_gtk_load ();
589 param = x264_gtk_param_get (x264_gtk);
599 width = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->width)), NULL));
600 height = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->height)), NULL));
601 fps_num = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->fps_num)), NULL));
602 fps_den = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->fps_den)), NULL));
603 frame_count = (gint)(g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (encode->frame_count)), NULL));
612 param->i_width = width;
613 param->i_height = height;
614 param->i_fps_num = fps_num;
615 param->i_fps_den = fps_den;
616 param->i_frame_total = frame_count;
619 if (pipe (fds) == -1)
622 thread_data = (X264_Thread_Data *)g_malloc0 (sizeof (X264_Thread_Data));
623 thread_data->param = param;
624 thread_data->file_input = g_strdup (file_input);
625 thread_data->file_output = g_strdup (file_output);
626 thread_data->in_container = encode->container;
627 thread_data->out_container = out_container;
628 g_free (file_output);
630 thread_data->io_read = g_io_channel_unix_new (fds[0]);
631 g_io_channel_set_encoding (thread_data->io_read, NULL, NULL);
632 thread_data->io_write = g_io_channel_unix_new (fds[1]);
633 g_io_channel_set_encoding (thread_data->io_write, NULL, NULL);
635 g_io_add_watch (thread_data->io_read, G_IO_IN,
636 (GIOFunc)_fill_status_window, thread_data);
638 win_status = x264_gtk_encode_status_window (thread_data);
639 gtk_window_set_transient_for (GTK_WINDOW (win_status), GTK_WINDOW (dialog));
640 gtk_window_set_modal (GTK_WINDOW (win_status), TRUE);
641 gtk_widget_show (win_status);
642 //gtk_widget_hide(thread_data->end_button);
644 thread = g_thread_create ((GThreadFunc)x264_gtk_encode_encode, thread_data, FALSE, NULL);
648 case GTK_RESPONSE_CLOSE:
651 _encode_shutdown ((X264_Gtk_Encode *)user_data);
656 _fill_status_window (GIOChannel *io __UNUSED__,
657 GIOCondition condition __UNUSED__,
661 X264_Thread_Data *thread_data;
662 X264_Pipe_Data pipe_data;
669 thread_data = (X264_Thread_Data *)user_data;
670 status = g_io_channel_read_chars (thread_data->io_read,
672 sizeof (X264_Pipe_Data),
674 if (status != G_IO_STATUS_NORMAL) {
675 g_print ("Error ! %d %d %d\n", status, sizeof (X264_Pipe_Data), size);
679 snprintf (str, 128, "%d/%d", pipe_data.frame, pipe_data.frame_total);
680 gtk_entry_set_text (GTK_ENTRY (thread_data->current_video_frame),
683 snprintf (str, 128, "%dKB",
684 pipe_data.file >> 10);
685 gtk_entry_set_text (GTK_ENTRY (thread_data->video_data),
688 fps = pipe_data.elapsed > 0 ? 1000000.0 * (gdouble)pipe_data.frame / (gdouble)pipe_data.elapsed : 0.0;
689 snprintf (str, 128, "%.2fKB/s (%.2f fps)",
690 (double) pipe_data.file * 8 * thread_data->param->i_fps_num /
691 ((double) thread_data->param->i_fps_den * pipe_data.frame * 1000),
693 gtk_entry_set_text (GTK_ENTRY (thread_data->video_rendering_rate),
696 snprintf (str, 128, "%lld:%02lld:%02lld",
697 (pipe_data.elapsed / 1000000) / 3600,
698 ((pipe_data.elapsed / 1000000) / 60) % 60,
699 (pipe_data.elapsed / 1000000) % 60);
700 gtk_entry_set_text (GTK_ENTRY (thread_data->time_elapsed),
703 eta = pipe_data.elapsed * (pipe_data.frame_total - pipe_data.frame) / ((int64_t)pipe_data.frame * 1000000);
704 snprintf (str, 128, "%d:%02d:%02d", eta / 3600, (eta / 60) % 60, eta % 60);
705 gtk_entry_set_text (GTK_ENTRY (thread_data->time_remaining),
708 progress = (gdouble)pipe_data.frame / (gdouble)pipe_data.frame_total;
709 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (thread_data->progress),
712 snprintf (str, 128, "%0.1f%%", 100.0 * progress);
713 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (thread_data->progress), str);