]> git.sesse.net Git - x264/blob - gtk/x264_gtk_encode_encode.c
GTK: compilation fixes on mingw,
[x264] / gtk / x264_gtk_encode_encode.c
1 #include <string.h>
2 #if defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ || defined __DragonFly__
3 #  include <inttypes.h>
4 #else
5 #  include <stdint.h>
6 #endif
7
8 #include <gtk/gtk.h>
9
10 #include "../config.h"
11 #include "../x264.h"
12 #include "../muxers.h"
13 #include "x264_gtk_encode_private.h"
14
15
16 #define DATA_MAX 3000000
17 uint8_t data[DATA_MAX];
18
19 int64_t x264_mdate (void);
20
21 /* input interface */
22 int           (*p_open_infile)( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param );
23 int           (*p_get_frame_total)( hnd_t handle );
24 int           (*p_read_frame)( x264_picture_t *p_pic, hnd_t handle, int i_frame );
25 int           (*p_close_infile)( hnd_t handle );
26
27 /* output interface */
28 static int (*p_open_outfile)      (char *filename, void **handle);
29 static int (*p_set_outfile_param) (void *handle, x264_param_t *p_param);
30 static int (*p_write_nalu)        (void *handle, uint8_t *p_nal, int i_size);
31 static int (*p_set_eop)           (void *handle, x264_picture_t *p_picture);
32 static int (*p_close_outfile)     (void *handle);
33
34 static int _set_drivers  (gint int_container, gint out_container);
35 static int _encode_frame (x264_t *h, void *handle, x264_picture_t *pic);
36
37
38 gpointer
39 x264_gtk_encode_encode (X264_Thread_Data *thread_data)
40 {
41   GIOStatus       status;
42   gsize           size;
43   X264_Pipe_Data  pipe_data;
44   x264_param_t   *param;
45   x264_picture_t  pic;
46   x264_t         *h;
47   hnd_t           hin;
48   hnd_t           hout;
49   int             i_frame;
50   int             i_frame_total;
51   int64_t         i_start;
52   int64_t         i_end;
53   int64_t         i_file;
54   int             i_frame_size;
55   int             i_progress;
56   int             err;
57
58   g_print ("encoding...\n");
59   param = thread_data->param;
60   err = _set_drivers (thread_data->in_container, thread_data->out_container);
61   if (err < 0) {
62     GtkWidget *no_driver;
63     no_driver = gtk_message_dialog_new (GTK_WINDOW(thread_data->dialog),
64                                         GTK_DIALOG_DESTROY_WITH_PARENT,
65                                         GTK_MESSAGE_ERROR,
66                                         GTK_BUTTONS_CLOSE,
67                                         (err == -2) ? "Error: unknown output file type"
68                                                     : "Error: unknown input file type");
69     gtk_dialog_run (GTK_DIALOG (no_driver));
70     gtk_widget_destroy (no_driver);
71     return NULL;
72   }
73     
74   if (p_open_infile (thread_data->file_input, &hin, param)) {
75     fprintf( stderr, "could not open input file '%s'\n", thread_data->file_input );
76     return NULL;
77   }
78
79   p_open_outfile ((char *)thread_data->file_output, &hout);
80
81   i_frame_total = p_get_frame_total (hin );
82   if (((i_frame_total == 0) || (param->i_frame_total < i_frame_total)) &&
83       (param->i_frame_total > 0))
84     i_frame_total = param->i_frame_total;
85   param->i_frame_total = i_frame_total;
86
87   if ((h = x264_encoder_open (param)) == NULL)
88     {
89       fprintf (stderr, "x264_encoder_open failed\n");
90       p_close_infile (hin);
91       p_close_outfile (hout);
92       g_free (param);
93
94       return NULL;
95     }
96
97   if (p_set_outfile_param (hout, param))
98     {
99       fprintf (stderr, "can't set outfile param\n");
100       p_close_infile (hin);
101       p_close_outfile (hout);
102       g_free (param);
103
104       return NULL;
105     }
106
107   /* Create a new pic */
108   x264_picture_alloc (&pic, X264_CSP_I420, param->i_width, param->i_height );
109
110   i_start = x264_mdate();
111
112   /* Encode frames */
113   for (i_frame = 0, i_file = 0, i_progress = 0;
114        ((i_frame < i_frame_total) || (i_frame_total == 0)); )
115     {
116       if (p_read_frame (&pic, hin, i_frame))
117         break;
118
119       pic.i_pts = (int64_t)i_frame * param->i_fps_den;
120
121       i_file += _encode_frame (h, hout, &pic);
122
123       i_frame++;
124
125       /* update status line (up to 1000 times per input file) */
126       if (param->i_log_level < X264_LOG_DEBUG && 
127           (i_frame_total ? i_frame * 1000 / i_frame_total > i_progress
128            : i_frame % 10 == 0))
129         {
130           int64_t i_elapsed = x264_mdate () - i_start;
131           double fps = i_elapsed > 0 ? i_frame * 1000000. / i_elapsed : 0;
132
133           if (i_frame_total)
134             {
135               pipe_data.frame = i_frame;
136               pipe_data.frame_total = i_frame_total;
137               pipe_data.file = i_file;
138               pipe_data.elapsed = i_elapsed;
139               status = g_io_channel_write_chars (thread_data->io_write,
140                                                  (const gchar *)&pipe_data,
141                                                  sizeof (X264_Pipe_Data),
142                                                  &size, NULL);
143               if (status != G_IO_STATUS_NORMAL) {
144                 g_print ("Error ! %d %d %d\n", status, sizeof (X264_Pipe_Data), size);
145               }
146               else {
147                 /* we force the GIOChannel to write to the pipeline */
148                 status = g_io_channel_flush (thread_data->io_write,
149                                              NULL);
150                 if (status != G_IO_STATUS_NORMAL) {
151                   g_print ("Error ! %d\n", status);
152                 }
153               }
154             }
155           else
156             fprintf( stderr, "encoded frames: %d, %.2f fps   \r", i_frame, fps );
157           fflush( stderr ); /* needed in windows */
158         }
159     }
160   /* Flush delayed B-frames */
161   do {
162     i_file += i_frame_size = _encode_frame (h, hout, NULL);
163   } while (i_frame_size);
164
165   i_end = x264_mdate ();
166   x264_picture_clean (&pic);
167   x264_encoder_close (h);
168   fprintf (stderr, "\n");
169
170   p_close_infile (hin);
171   p_close_outfile (hout);
172
173   if (i_frame > 0) {
174     double fps = (double)i_frame * (double)1000000 /
175       (double)(i_end - i_start);
176
177     fprintf (stderr, "encoded %d frames, %.2f fps, %.2f kb/s\n",
178              i_frame, fps,
179              (double) i_file * 8 * param->i_fps_num /
180              ((double) param->i_fps_den * i_frame * 1000));
181   }
182
183   gtk_widget_set_sensitive (thread_data->end_button, TRUE);
184   gtk_widget_hide (thread_data->button);
185   return NULL;
186 }
187
188 static int
189 _set_drivers (gint in_container, gint out_container)
190 {
191   switch (in_container) {
192   case 0: /* YUV */
193   case 1: /* CIF */
194   case 2: /* QCIF */
195       /*   Default input file driver */
196       p_open_infile = open_file_yuv;
197       p_get_frame_total = get_frame_total_yuv;
198       p_read_frame = read_frame_yuv;
199       p_close_infile = close_file_yuv;
200       break;
201 #ifdef AVIS_INPUT
202     case 3: /* AVI */
203     case 4: /* AVS */
204       p_open_infile = open_file_avis;
205       p_get_frame_total = get_frame_total_avis;
206       p_read_frame = read_frame_avis;
207       p_close_infile = close_file_avis;
208     break;
209 #endif
210     default: /* Unknown */
211       return -1;
212   }
213
214   switch (out_container) {
215   case 0:
216 /*     Raw ES output file driver */
217     p_open_outfile = open_file_bsf;
218     p_set_outfile_param = set_param_bsf;
219     p_write_nalu = write_nalu_bsf;
220     p_set_eop = set_eop_bsf;
221     p_close_outfile = close_file_bsf;
222     break;
223   case 1:
224 /*     Matroska output file driver */
225     p_open_outfile = open_file_mkv;
226     p_set_outfile_param = set_param_mkv;
227     p_write_nalu = write_nalu_mkv;
228     p_set_eop = set_eop_mkv;
229     p_close_outfile = close_file_mkv;
230     break;
231 #ifdef MP4_OUTPUT
232   case 2:
233     p_open_outfile = open_file_mp4;
234     p_set_outfile_param = set_param_mp4;
235     p_write_nalu = write_nalu_mp4;
236     p_set_eop = set_eop_mp4;
237     p_close_outfile = close_file_mp4;
238     break;
239 #endif
240   default:
241     return -2;
242   }
243
244   return 1;
245 }
246
247 static int
248 _encode_frame (x264_t *h, void *handle, x264_picture_t *pic)
249 {
250   x264_picture_t pic_out;
251   x264_nal_t    *nal;
252   int            i_nal;
253   int            i;
254   int            i_file = 0;
255
256   /* Do not force any parameters */
257   if (pic)
258     {
259       pic->i_type = X264_TYPE_AUTO;
260       pic->i_qpplus1 = 0;
261     }
262   if (x264_encoder_encode (h, &nal, &i_nal, pic, &pic_out) < 0)
263     {
264       fprintf (stderr, "x264_encoder_encode failed\n");
265     }
266
267   for (i = 0; i < i_nal; i++)
268     {
269       int i_size;
270       int i_data;
271
272       i_data = DATA_MAX;
273       if ((i_size = x264_nal_encode (data, &i_data, 1, &nal[i])) > 0 )
274         {
275           i_file += p_write_nalu (handle, data, i_size);
276         }
277       else if (i_size < 0)
278         {
279           fprintf (stderr, "need to increase buffer size (size=%d)\n", -i_size);
280         }
281     }
282   if (i_nal)
283     p_set_eop (handle, &pic_out);
284
285   return i_file;
286 }