]> git.sesse.net Git - vlc/blob - modules/codec/x264.c
x264 options patch by Alex Izvorski (plus some checks on x264 version)
[vlc] / modules / codec / x264.c
1 /*****************************************************************************
2  * x264.c: h264 video encoder
3  *****************************************************************************
4  * Copyright (C) 2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <vlc/vlc.h>
28 #include <vlc/vout.h>
29 #include <vlc/sout.h>
30 #include <vlc/decoder.h>
31
32 #include <x264.h>
33
34 #define SOUT_CFG_PREFIX "sout-x264-"
35
36 /*****************************************************************************
37  * Module descriptor
38  *****************************************************************************/
39 static int  Open ( vlc_object_t * );
40 static void Close( vlc_object_t * );
41
42 #define QP_TEXT N_("Quantizer parameter")
43 #define QP_LONGTEXT N_( \
44     "This selects the quantizer to use (1 to 51). Lower values result in " \
45     "better fidelity, but higher bitrates. 26 is a good default value." )
46
47 #define QPMIN_TEXT N_("Minimum quantizer parameter")
48 #define QPMIN_LONGTEXT N_( "Minimum quantizer, 15/35 seems to be a useful " \
49     "range." )
50
51 #define QPMAX_TEXT N_("Maximum quantizer parameter")
52 #define QPMAX_LONGTEXT N_( "Maximum quantizer parameter." )
53
54 #define CABAC_TEXT N_("Enable CABAC")
55 #define CABAC_LONGTEXT N_( "Enable CABAC (Context-Adaptive Binary Arithmetic "\
56     "Coding). Slightly slows down encoding and decoding, but should save " \
57     "10-15% bitrate." )
58
59 #define LOOPF_TEXT N_("Enable loop filter")
60 #define LOOPF_LONGTEXT N_( "Use deblocking loop filter (increases quality).")
61
62 #define ANALYSE_TEXT N_("Analyse mode")
63 #define ANALYSE_LONGTEXT N_( "This selects the analysing mode.")
64
65 #define TOLERANCE_TEXT N_("Bitrate tolerance")
66 #define TOLERANCE_LONGTEXT N_( "Sets the allowed variance in average " \
67     "bitrate.")
68
69 #define VBV_MAXRATE_TEXT N_("Maximum local bitrate")
70 #define VBV_MAXRATE_LONGTEXT N_( "Sets a maximum local bitrate in kbits/s.")
71
72 #define VBV_BUFSIZE_TEXT N_("Averaging period for the maximum local bitrate")
73 #define VBV_BUFSIZE_LONGTEXT N_( "Sets an averaging period for the maximum " \
74     "local bitrate, in kbits/s.")
75
76 #define VBV_INIT_TEXT N_("Initial buffer occupancy")
77 #define VBV_INIT_LONGTEXT N_( "Sets the initial buffer occupancy as a " \
78     "fraction of the buffer size.")
79
80 #define KEYINT_TEXT N_("Sets maximum interval between IDR-frames")
81 #define KEYINT_LONGTEXT N_( "Larger values save bits, thus improve quality "\
82     "for a given bitrate, at the cost of seeking precision." )
83
84 #define KEYINT_MIN_TEXT N_("Sets minimum interval between IDR-frames")
85 #define KEYINT_MIN_LONGTEXT N_("In H.264, I-Frames do not necessarily bound " \
86     "a closed GOP because it is allowable for a P-frame to be predicted from "\
87     "more frames than just the one frame before it (also see frameref). " \
88     "Therefore, I-frames are not necessarily seekable. " \
89     "IDR-Frames restrict subsequent P-frames from referring to any frame " \
90     "prior to the IDR-Frame. \n" \
91     "If scenecuts appear within this interval, they are still encoded as " \
92     "I-frames, but do not start a new GOP. Default value is keyint * 0.4." )
93
94 #define BFRAMES_TEXT N_("B frames")
95 #define BFRAMES_LONGTEXT N_( "Number of consecutive B-Frames between I and " \
96     "P-frames." )
97
98 #define BPYRAMID_TEXT N_("B pyramid")
99 #define BPYRAMID_LONGTEXT N_( "Allows B-frames to be used as references for " \
100     "predicting other frames." )
101
102 #define FRAMEREF_TEXT N_("Number of previous frames used as predictors.")
103 #define FRAMEREF_LONGTEXT N_( "This is effective in Anime, but seems to " \
104     "make little difference in live-action source material. Some decoders " \
105     "are unable to deal with large frameref values." )
106
107 #define SCENE_TEXT N_("Scene-cut detection.")
108 #define SCENE_LONGTEXT N_( "Controls how aggressively to insert extra " \
109     "I-frames. With small values of scenecut, the codec often has to force " \
110     "an I-frame when it would exceed keyint. " \
111     "Good values of scenecut may find a better location for the I-frame. " \
112     "Large values use more I-frames than necessary, thus wasting bits. " \
113     "-1 disables scene-cut detection, so I-frames are be inserted only every "\
114     "other keyint frames, which probably leads to ugly encoding artifacts." )
115
116 #define SUBPEL_TEXT N_("Sub-pixel refinement quality.")
117 #define SUBPEL_LONGTEXT N_( "This parameter controls quality versus speed " \
118     "tradeoffs involved in the motion estimation decision process " \
119     "(lower = quicker and higher = better quality)." )
120
121 #define ME_TEXT N_("Motion estimation algorithm.")
122 #define ME_LONGTEXT N_( "Selects the motion estimation algorithm: "\
123     " dia - diamond (fastest) \n" \
124     " hex - hexagon (default setting) \n" \
125     " umh - uneven multi-hexagon (better but slower) \n" \
126     " esa - exhaustive search (extremely slow, primarily for testing) " )
127
128 #define MERANGE_TEXT N_("Motion estimation search range.")
129 #define MERANGE_LONGTEXT N_( "Maximum distance to search for motion estimation, "\
130     "measured from predicted position(s). Default of 16 is good for most footage, "\
131     "high motion sequences may benefit from settings between 24-32." )
132
133 #define NO_PSNR_TEXT N_("Disable PSNR calculation.")
134 #define NO_PSNR_LONGTEXT N_( "This has no effect on actual encoding quality, "\
135     "it just prevents the stats from being calculated (for speed)." )
136
137 #define NO_B_ADAPT_TEXT N_("Disable adaptive B-frames.")
138 #define NO_B_ADAPT_LONGTEXT N_( "If this is on, the specified number of consequtive B-frames "\
139     "will always be used, except possibly before an I-frame. " )
140
141 #define B_BIAS_TEXT N_("Bias the choice to use B-frames.")
142 #define B_BIAS_LONGTEXT N_( "Positive values cause more= B-frames, negative values cause less B-frames. " )
143
144
145 #if X264_BUILD >= 23
146 static char *enc_me_list[] =
147   { "", "dia", "hex", "umh", "esa" };
148 static char *enc_me_list_text[] =
149   { N_("default"), N_("dia"), N_("hex"), N_("umh"), N_("esa") };
150 #endif
151
152 static char *enc_analyse_list[] =
153   { "", "all", "normal", "fast", "none" };
154 static char *enc_analyse_list_text[] =
155   { N_("default"), N_("all"), N_("slow"), N_("normal"),
156     N_("fast"), N_("none") };
157
158 vlc_module_begin();
159     set_description( _("H264 encoder (using x264 library)"));
160     set_capability( "encoder", 200 );
161     set_callbacks( Open, Close );
162     set_category( CAT_INPUT );
163     set_subcategory( SUBCAT_INPUT_VCODEC );
164
165     add_integer( SOUT_CFG_PREFIX "qp", 0, NULL, QP_TEXT, QP_LONGTEXT,
166                  VLC_FALSE );
167         change_integer_range( 0, 51 );
168     add_integer( SOUT_CFG_PREFIX "qp-min", 10, NULL, QPMIN_TEXT,
169                  QPMIN_LONGTEXT, VLC_FALSE );
170         change_integer_range( 0, 51 );
171     add_integer( SOUT_CFG_PREFIX "qp-max", 51, NULL, QPMAX_TEXT,
172                  QPMAX_LONGTEXT, VLC_FALSE );
173         change_integer_range( 0, 51 );
174
175     add_bool( SOUT_CFG_PREFIX "cabac", 1, NULL, CABAC_TEXT, CABAC_LONGTEXT,
176               VLC_FALSE );
177
178     add_bool( SOUT_CFG_PREFIX "loopfilter", 1, NULL, LOOPF_TEXT,
179               LOOPF_LONGTEXT, VLC_FALSE );
180
181     add_string( SOUT_CFG_PREFIX "analyse", "", NULL, ANALYSE_TEXT,
182                 ANALYSE_LONGTEXT, VLC_FALSE );
183         change_string_list( enc_analyse_list, enc_analyse_list_text, 0 );
184
185     add_float( SOUT_CFG_PREFIX "tolerance", 1.0, NULL, TOLERANCE_TEXT,
186                TOLERANCE_LONGTEXT, VLC_FALSE );
187         change_float_range( 0, 100 );
188
189     add_integer( SOUT_CFG_PREFIX "vbv-maxrate", 0, NULL, VBV_MAXRATE_TEXT,
190                  VBV_MAXRATE_LONGTEXT, VLC_FALSE );
191
192     add_integer( SOUT_CFG_PREFIX "vbv-bufsize", 0, NULL, VBV_BUFSIZE_TEXT,
193                  VBV_BUFSIZE_LONGTEXT, VLC_FALSE );
194
195     add_float( SOUT_CFG_PREFIX "vbv-init", 0.9, NULL, VBV_INIT_TEXT,
196                VBV_INIT_LONGTEXT, VLC_FALSE );
197         change_float_range( 0, 1 );
198
199     add_integer( SOUT_CFG_PREFIX "keyint", 250, NULL, KEYINT_TEXT,
200                  KEYINT_LONGTEXT, VLC_FALSE );
201
202     add_integer( SOUT_CFG_PREFIX "keyint-min", 0, NULL, KEYINT_MIN_TEXT,
203                  KEYINT_MIN_LONGTEXT, VLC_FALSE );
204
205     add_integer( SOUT_CFG_PREFIX "bframes", 0, NULL, BFRAMES_TEXT,
206                  BFRAMES_LONGTEXT, VLC_FALSE );
207         change_integer_range( 0, 16 );
208
209     add_bool( SOUT_CFG_PREFIX "bpyramid", 0, NULL, BPYRAMID_TEXT,
210               BPYRAMID_LONGTEXT, VLC_FALSE );
211
212     add_integer( SOUT_CFG_PREFIX "frameref", 1, NULL, FRAMEREF_TEXT,
213                  FRAMEREF_LONGTEXT, VLC_FALSE );
214         change_integer_range( 1, 15 );
215
216     add_integer( SOUT_CFG_PREFIX "scenecut", 40, NULL, SCENE_TEXT,
217                  SCENE_LONGTEXT, VLC_FALSE );
218         change_integer_range( -1, 100 );
219
220 #if X264_BUILD >= 30
221     add_integer( SOUT_CFG_PREFIX "subpel", 6, NULL, SUBPEL_TEXT,
222                  SUBPEL_LONGTEXT, VLC_FALSE );
223         change_integer_range( 1, 6 );
224 #else
225     add_integer( SOUT_CFG_PREFIX "subpel", 5, NULL, SUBPEL_TEXT,
226                  SUBPEL_LONGTEXT, VLC_FALSE );
227         change_integer_range( 1, 5 );
228 #endif
229
230 #if X264_BUILD >= 23
231 /* r221 */    add_string( SOUT_CFG_PREFIX "me", "hex", NULL, ME_TEXT,
232                 ME_LONGTEXT, VLC_FALSE );
233         change_string_list( enc_me_list, enc_me_list_text, 0 );
234
235 /* r221 */    add_integer( SOUT_CFG_PREFIX "merange", 16, NULL, MERANGE_TEXT,
236                  MERANGE_LONGTEXT, VLC_FALSE );
237         change_integer_range( 1, 64 );
238 #endif
239
240 /* r44 */    add_bool( SOUT_CFG_PREFIX "no-psnr", 0, NULL, NO_PSNR_TEXT,
241               NO_PSNR_LONGTEXT, VLC_FALSE );
242
243 #if X264_BUILD >= 0x0013
244 /* r137 */    add_bool( SOUT_CFG_PREFIX "no-b-adapt", 0, NULL, NO_B_ADAPT_TEXT,
245               NO_B_ADAPT_LONGTEXT, VLC_FALSE );
246
247 /* r137 */    add_integer( SOUT_CFG_PREFIX "b-bias", 0, NULL, B_BIAS_TEXT,
248                  B_BIAS_LONGTEXT, VLC_FALSE );
249         change_integer_range( -100, 100 );
250 #endif
251
252
253 vlc_module_end();
254
255 /*****************************************************************************
256  * Local prototypes
257  *****************************************************************************/
258 static const char *ppsz_sout_options[] = {
259     "qp", "qp-min", "qp-max", "cabac", "loopfilter", "analyse",
260     "keyint", "keyint-min", "bframes", "bpyramid", "frameref", "scenecut",
261     "subpel", "me", "merange", "no-psnr", "no-b-adapt", "b-bias", "tolerance", 
262     "vbv-maxrate", "vbv-bufsize", "vbv-init", NULL
263 };
264
265 static block_t *Encode( encoder_t *, picture_t * );
266
267 struct encoder_sys_t
268 {
269     x264_t          *h;
270     x264_param_t    param;
271
272     int             i_buffer;
273     uint8_t         *p_buffer;
274
275     mtime_t         i_last_ref_pts;
276 };
277
278 /*****************************************************************************
279  * Open: probe the encoder
280  *****************************************************************************/
281 static int  Open ( vlc_object_t *p_this )
282 {
283     encoder_t     *p_enc = (encoder_t *)p_this;
284     encoder_sys_t *p_sys;
285     vlc_value_t    val;
286     int i_qmin = 0, i_qmax = 0;
287
288     if( p_enc->fmt_out.i_codec != VLC_FOURCC( 'h', '2', '6', '4' ) &&
289         !p_enc->b_force )
290     {
291         return VLC_EGENERIC;
292     }
293
294 #if X264_BUILD < 37
295     if( p_enc->fmt_in.video.i_width % 16 != 0 ||
296         p_enc->fmt_in.video.i_height % 16!= 0 )
297     {
298         msg_Warn( p_enc, "size is not a multiple of 16 (%ix%i)",
299                   p_enc->fmt_in.video.i_width, p_enc->fmt_in.video.i_height );
300
301         if( p_enc->fmt_in.video.i_width < 16 ||
302             p_enc->fmt_in.video.i_height < 16 )
303         {
304             msg_Err( p_enc, "video is too small to be cropped" );
305             return VLC_EGENERIC;
306         }
307
308         msg_Warn( p_enc, "cropping video to %ix%i",
309                   p_enc->fmt_in.video.i_width >> 4 << 4,
310                   p_enc->fmt_in.video.i_height >> 4 << 4 );
311     }
312 #endif
313
314     sout_CfgParse( p_enc, SOUT_CFG_PREFIX, ppsz_sout_options, p_enc->p_cfg );
315
316     p_enc->fmt_out.i_codec = VLC_FOURCC( 'h', '2', '6', '4' );
317     p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','0');
318
319     p_enc->pf_encode_video = Encode;
320     p_enc->pf_encode_audio = NULL;
321     p_enc->p_sys = p_sys = malloc( sizeof( encoder_sys_t ) );
322     p_sys->i_last_ref_pts = 0;
323
324     x264_param_default( &p_sys->param );
325     p_sys->param.i_width  = p_enc->fmt_in.video.i_width;
326     p_sys->param.i_height = p_enc->fmt_in.video.i_height;
327 #if X264_BUILD < 37
328     p_sys->param.i_width  = p_sys->param.i_width >> 4 << 4;
329     p_sys->param.i_height = p_sys->param.i_height >> 4 << 4;
330 #endif
331
332     var_Get( p_enc, SOUT_CFG_PREFIX "qp-min", &val );
333     if( val.i_int >= 1 && val.i_int <= 51 ) i_qmin = val.i_int;
334     var_Get( p_enc, SOUT_CFG_PREFIX "qp-max", &val );
335     if( val.i_int >= 1 && val.i_int <= 51 ) i_qmax = val.i_int;
336
337     var_Get( p_enc, SOUT_CFG_PREFIX "qp", &val );
338     if( val.i_int >= 1 && val.i_int <= 51 )
339     {
340         if( i_qmin > val.i_int ) i_qmin = val.i_int;
341         if( i_qmax < val.i_int ) i_qmax = val.i_int;
342
343 #if X264_BUILD >= 0x000a
344         p_sys->param.rc.i_qp_constant = val.i_int;
345         p_sys->param.rc.i_qp_min = i_qmin;
346         p_sys->param.rc.i_qp_max = i_qmax;
347 #else
348         p_sys->param.i_qp_constant = val.i_int;
349 #endif
350     }
351     else
352     {
353         /* No QP -> constant bitrate */
354 #if X264_BUILD >= 0x000a
355         p_sys->param.rc.b_cbr = 1;
356         p_sys->param.rc.i_bitrate = p_enc->fmt_out.i_bitrate / 1000;
357
358 #if X264_BUILD >= 24
359         var_Get( p_enc, SOUT_CFG_PREFIX "tolerance", &val );
360         p_sys->param.rc.f_rate_tolerance = val.f_float;
361
362         var_Get( p_enc, SOUT_CFG_PREFIX "vbv-maxrate", &val );
363         p_sys->param.rc.i_vbv_max_bitrate = val.i_int;
364
365         var_Get( p_enc, SOUT_CFG_PREFIX "vbv-bufsize", &val );
366         p_sys->param.rc.i_vbv_buffer_size = val.i_int;
367         if( !val.i_int )
368             p_sys->param.rc.i_vbv_buffer_size = p_sys->param.rc.i_bitrate;
369
370         var_Get( p_enc, SOUT_CFG_PREFIX "vbv-init", &val );
371         p_sys->param.rc.f_vbv_buffer_init = val.f_float;
372 #else
373         p_sys->param.rc.i_rc_buffer_size = p_sys->param.rc.i_bitrate;
374         p_sys->param.rc.i_rc_init_buffer = p_sys->param.rc.i_bitrate / 4;
375 #endif
376 #endif
377     }
378
379     var_Get( p_enc, SOUT_CFG_PREFIX "cabac", &val );
380     p_sys->param.b_cabac = val.b_bool;
381
382     var_Get( p_enc, SOUT_CFG_PREFIX "loopfilter", &val );
383     p_sys->param.b_deblocking_filter = val.b_bool;
384
385     var_Get( p_enc, SOUT_CFG_PREFIX "keyint", &val );
386 #if X264_BUILD >= 0x000e
387     if( val.i_int > 0 ) p_sys->param.i_keyint_max = val.i_int;
388     if( val.i_int > 0 ) p_sys->param.i_keyint_min = val.i_int * 0.4;
389 #else
390     if( val.i_int > 0 ) p_sys->param.i_iframe = val.i_int;
391 #endif
392
393     var_Get( p_enc, SOUT_CFG_PREFIX "keyint-min", &val );
394 #if X264_BUILD >= 0x000e
395     if( val.i_int > 0 ) p_sys->param.i_keyint_min = val.i_int;
396 #else
397     if( val.i_int > 0 ) p_sys->param.i_idrframe = val.i_int;
398 #endif
399
400     var_Get( p_enc, SOUT_CFG_PREFIX "bframes", &val );
401     if( val.i_int >= 0 && val.i_int <= 16 ) p_sys->param.i_bframe = val.i_int;
402
403 #if X264_BUILD >= 22
404     var_Get( p_enc, SOUT_CFG_PREFIX "bpyramid", &val );
405     p_sys->param.b_bframe_pyramid = val.b_bool;
406 #endif
407
408     var_Get( p_enc, SOUT_CFG_PREFIX "frameref", &val );
409     if( val.i_int > 0 && val.i_int <= 15 )
410         p_sys->param.i_frame_reference = val.i_int;
411
412     var_Get( p_enc, SOUT_CFG_PREFIX "scenecut", &val );
413 #if X264_BUILD >= 0x000b
414     if( val.i_int >= -1 && val.i_int <= 100 )
415         p_sys->param.i_scenecut_threshold = val.i_int;
416 #endif
417
418 #if X264_BUILD >= 22
419     var_Get( p_enc, SOUT_CFG_PREFIX "subpel", &val );
420 #if X264_BUILD >= 30
421     if( val.i_int >= 1 && val.i_int <= 6 )
422 #else
423     if( val.i_int >= 1 && val.i_int <= 5 )
424 #endif
425         p_sys->param.analyse.i_subpel_refine = val.i_int;
426 #endif
427
428 #if X264_BUILD >= 23
429     var_Get( p_enc, SOUT_CFG_PREFIX "me", &val );
430     if( !strcmp( val.psz_string, "dia" ) )
431     {
432         p_sys->param.analyse.i_me_method = X264_ME_DIA;
433     }
434     else if( !strcmp( val.psz_string, "hex" ) )
435     {
436         p_sys->param.analyse.i_me_method = X264_ME_HEX;
437     }
438     else if( !strcmp( val.psz_string, "umh" ) )
439     {
440         p_sys->param.analyse.i_me_method = X264_ME_UMH;
441     }
442     else if( !strcmp( val.psz_string, "esa" ) )
443     {
444         p_sys->param.analyse.i_me_method = X264_ME_ESA;
445     }
446     if( val.psz_string ) free( val.psz_string );
447
448     var_Get( p_enc, SOUT_CFG_PREFIX "merange", &val );
449     if( val.i_int >= 1 && val.i_int <= 64 ) p_sys->param.analyse.i_me_range = val.i_int;
450 #endif
451
452     var_Get( p_enc, SOUT_CFG_PREFIX "no-psnr", &val );
453     p_sys->param.analyse.b_psnr = ! val.b_bool;
454
455 #if X264_BUILD >= 0x0013
456     var_Get( p_enc, SOUT_CFG_PREFIX "no-b-adapt", &val );
457     p_sys->param.b_bframe_adaptive = ! val.b_bool;
458
459     var_Get( p_enc, SOUT_CFG_PREFIX "b-bias", &val );
460     if( val.i_int >= -100 && val.i_int <= 100 )
461         p_sys->param.i_bframe_bias = val.i_int;
462 #endif
463
464 #ifndef X264_ANALYSE_BSUB16x16
465 #   define X264_ANALYSE_BSUB16x16 0
466 #endif
467     var_Get( p_enc, SOUT_CFG_PREFIX "analyse", &val );
468     if( !strcmp( val.psz_string, "none" ) )
469     {
470         p_sys->param.analyse.inter = 0;
471     }
472     else if( !strcmp( val.psz_string, "fast" ) )
473     {
474         p_sys->param.analyse.inter = X264_ANALYSE_I4x4;
475     }
476     else if( !strcmp( val.psz_string, "normal" ) )
477     {
478         p_sys->param.analyse.inter =
479             X264_ANALYSE_I4x4 | X264_ANALYSE_PSUB16x16;
480     }
481     else if( !strcmp( val.psz_string, "slow" ) )
482     {
483         p_sys->param.analyse.inter =
484             X264_ANALYSE_I4x4 |
485             X264_ANALYSE_PSUB16x16 | X264_ANALYSE_PSUB8x8 |
486             X264_ANALYSE_BSUB16x16;
487     }
488     else if( !strcmp( val.psz_string, "all" ) )
489     {
490         p_sys->param.analyse.inter =
491             X264_ANALYSE_I4x4 |
492             X264_ANALYSE_PSUB16x16 | X264_ANALYSE_PSUB8x8 |
493             X264_ANALYSE_BSUB16x16;
494 #ifdef X264_ANALYSE_I8x8
495         p_sys->param.analyse.inter |= X264_ANALYSE_I8x8;
496         p_sys->param.analyse.b_transform_8x8 = 1;
497 #endif
498     }
499     if( val.psz_string ) free( val.psz_string );
500
501     if( p_enc->fmt_in.video.i_aspect > 0 )
502     {
503         int64_t i_num, i_den;
504         int i_dst_num, i_dst_den;
505
506         i_num = p_enc->fmt_in.video.i_aspect *
507             (int64_t)p_enc->fmt_in.video.i_height;
508         i_den = VOUT_ASPECT_FACTOR * p_enc->fmt_in.video.i_width;
509         vlc_ureduce( &i_dst_num, &i_dst_den, i_num, i_den, 0 );
510
511         p_sys->param.vui.i_sar_width = i_dst_num;
512         p_sys->param.vui.i_sar_height = i_dst_den;
513     }
514     if( p_enc->fmt_in.video.i_frame_rate_base > 0 )
515     {
516         p_sys->param.i_fps_num = p_enc->fmt_in.video.i_frame_rate;
517         p_sys->param.i_fps_den = p_enc->fmt_in.video.i_frame_rate_base;
518     }
519     if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_MMX) )
520     {
521         p_sys->param.cpu &= ~X264_CPU_MMX;
522     }
523     if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_MMXEXT) )
524     {
525         p_sys->param.cpu &= ~X264_CPU_MMXEXT;
526     }
527     if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_SSE) )
528     {
529         p_sys->param.cpu &= ~X264_CPU_SSE;
530     }
531     if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_SSE2) )
532     {
533         p_sys->param.cpu &= ~X264_CPU_SSE2;
534     }
535
536 #if X264_BUILD >= 29
537     if( p_enc->i_threads >= 1 )
538         p_sys->param.i_threads = p_enc->i_threads;
539 #endif
540
541     /* Open the encoder */
542     p_sys->h = x264_encoder_open( &p_sys->param );
543
544     /* alloc mem */
545     p_sys->i_buffer = 4 * p_enc->fmt_in.video.i_width *
546         p_enc->fmt_in.video.i_height + 1000;
547     p_sys->p_buffer = malloc( p_sys->i_buffer );
548
549     /* get the globals headers */
550     p_enc->fmt_out.i_extra = 0;
551     p_enc->fmt_out.p_extra = NULL;
552
553 #if 0
554     x264_encoder_headers( p_sys->h, &nal, &i_nal );
555     for( i = 0; i < i_nal; i++ )
556     {
557         int i_size = p_sys->i_buffer;
558
559         x264_nal_encode( p_sys->p_buffer, &i_size, 1, &nal[i] );
560
561         p_enc->fmt_out.p_extra = realloc( p_enc->fmt_out.p_extra, p_enc->fmt_out.i_extra + i_size );
562
563         memcpy( p_enc->fmt_out.p_extra + p_enc->fmt_out.i_extra,
564                 p_sys->p_buffer, i_size );
565
566         p_enc->fmt_out.i_extra += i_size;
567     }
568 #endif
569
570     return VLC_SUCCESS;
571 }
572
573 /****************************************************************************
574  * Encode:
575  ****************************************************************************/
576 static block_t *Encode( encoder_t *p_enc, picture_t *p_pict )
577 {
578     encoder_sys_t *p_sys = p_enc->p_sys;
579     x264_picture_t pic;
580     x264_nal_t *nal;
581     block_t *p_block;
582     int i_nal, i_out, i;
583
584     /* init pic */
585     memset( &pic, 0, sizeof( x264_picture_t ) );
586     pic.i_pts = p_pict->date;
587     pic.img.i_csp = X264_CSP_I420;
588     pic.img.i_plane = p_pict->i_planes;
589     for( i = 0; i < p_pict->i_planes; i++ )
590     {
591         pic.img.plane[i] = p_pict->p[i].p_pixels;
592         pic.img.i_stride[i] = p_pict->p[i].i_pitch;
593     }
594
595 #if X264_BUILD >= 0x0013
596     x264_encoder_encode( p_sys->h, &nal, &i_nal, &pic, &pic );
597 #else
598     x264_encoder_encode( p_sys->h, &nal, &i_nal, &pic );
599 #endif
600
601     if( !i_nal ) return NULL;
602
603     for( i = 0, i_out = 0; i < i_nal; i++ )
604     {
605         int i_size = p_sys->i_buffer - i_out;
606         x264_nal_encode( p_sys->p_buffer + i_out, &i_size, 1, &nal[i] );
607
608         i_out += i_size;
609     }
610
611     p_block = block_New( p_enc, i_out );
612     memcpy( p_block->p_buffer, p_sys->p_buffer, i_out );
613
614     if( pic.i_type == X264_TYPE_IDR || pic.i_type == X264_TYPE_I )
615         p_block->i_flags |= BLOCK_FLAG_TYPE_I;
616     else if( pic.i_type == X264_TYPE_P )
617         p_block->i_flags |= BLOCK_FLAG_TYPE_P;
618     else if( pic.i_type == X264_TYPE_B )
619         p_block->i_flags |= BLOCK_FLAG_TYPE_B;
620
621     /* This isn't really valid for streams with B-frames */
622     p_block->i_length = I64C(1000000) *
623         p_enc->fmt_in.video.i_frame_rate_base /
624             p_enc->fmt_in.video.i_frame_rate;
625
626     p_block->i_dts = p_block->i_pts = pic.i_pts;
627
628     if( p_sys->param.i_bframe > 0 )
629     {
630         if( p_block->i_flags & BLOCK_FLAG_TYPE_B )
631         {
632             p_block->i_dts = p_block->i_pts;
633         }
634         else
635         {
636             if( p_sys->i_last_ref_pts )
637             {
638                 p_block->i_dts = p_sys->i_last_ref_pts;
639             }
640             else
641             {
642                 /* Let's put something sensible */
643                 p_block->i_dts = p_block->i_pts;
644             }
645
646             p_sys->i_last_ref_pts = p_block->i_pts;
647         }
648     }
649
650     return p_block;
651 }
652
653 /*****************************************************************************
654  * CloseEncoder: x264 encoder destruction
655  *****************************************************************************/
656 static void Close( vlc_object_t *p_this )
657 {
658     encoder_t     *p_enc = (encoder_t *)p_this;
659     encoder_sys_t *p_sys = p_enc->p_sys;
660
661     x264_encoder_close( p_sys->h );
662     free( p_sys->p_buffer );
663     free( p_sys );
664 }