]> git.sesse.net Git - vlc/blob - modules/codec/x264.c
* x264: compilation fix.
[vlc] / modules / codec / x264.c
1 /*****************************************************************************
2  * x264.c: h264 video encoder
3  *****************************************************************************
4  * Copyright (C) 2004 VideoLAN
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 /*****************************************************************************
35  * Module descriptor
36  *****************************************************************************/
37 static int  Open ( vlc_object_t * );
38 static void Close( vlc_object_t * );
39
40 #define SOUT_CFG_PREFIX "sout-x264-"
41 static char *enc_analyse_list[] = {
42     "all", "slowest", "slow", "normal", "fast", "fastest", "none"
43 };
44
45 static char *enc_analyse_list_text[] = {
46     N_("all"), N_("slowest"), N_("slow"), N_("normal"), N_("fast"), N_("fastest"), N_("none")
47 };
48
49 vlc_module_begin();
50     set_description( _("h264 video encoder using x264 library"));
51     set_capability( "encoder", 200 );
52
53     add_integer( SOUT_CFG_PREFIX "qp", 0, NULL, "Set fixed QP (1-51)", "", VLC_FALSE );
54     add_bool( SOUT_CFG_PREFIX "cabac", 1, NULL, "Enable CABAC", "", VLC_FALSE );
55     add_bool( SOUT_CFG_PREFIX "loopfilter", 1, NULL, "Enable loop filter", "", VLC_FALSE );
56
57     add_string( SOUT_CFG_PREFIX "analyse", "", NULL, "Analyse mode", "", VLC_FALSE );
58         change_string_list( enc_analyse_list, enc_analyse_list_text, 0 );
59     set_callbacks( Open, Close );
60 vlc_module_end();
61
62
63 /*****************************************************************************
64  * Local prototypes
65  *****************************************************************************/
66 static const char *ppsz_sout_options[] = {
67     "qp", "cabac", "loopfilter", "analyse", NULL
68 };
69
70 static block_t *Encode( encoder_t *, picture_t * );
71
72 struct encoder_sys_t
73 {
74     x264_t          *h;
75     x264_param_t    param;
76     x264_picture_t  *pic;
77
78     int             i_buffer;
79     uint8_t         *p_buffer;
80 };
81
82 /*****************************************************************************
83  * Open: probe the encoder
84  *****************************************************************************/
85 static int  Open ( vlc_object_t *p_this )
86 {
87     encoder_t     *p_enc = (encoder_t *)p_this;
88     encoder_sys_t *p_sys;
89     vlc_value_t    val;
90
91     if( p_enc->fmt_out.i_codec != VLC_FOURCC( 'h', '2', '6', '4' ) && !p_enc->b_force )
92     {
93         return VLC_EGENERIC;
94     }
95     if( p_enc->fmt_in.video.i_width % 16 != 0 ||
96         p_enc->fmt_in.video.i_height % 16!= 0 )
97     {
98         msg_Warn( p_enc, "invalid size %ix%i",
99                   p_enc->fmt_in.video.i_width,
100                   p_enc->fmt_in.video.i_height );
101         return VLC_EGENERIC;
102     }
103
104     sout_ParseCfg( p_enc, SOUT_CFG_PREFIX, ppsz_sout_options, p_enc->p_cfg );
105
106     p_enc->fmt_out.i_codec = VLC_FOURCC( 'h', '2', '6', '4' );
107     p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','0');
108
109     p_enc->pf_encode_video = Encode;
110     p_enc->pf_encode_audio = NULL;
111     p_enc->p_sys = p_sys = malloc( sizeof( encoder_sys_t ) );
112
113     x264_param_default( &p_sys->param );
114     p_sys->param.i_width  = p_enc->fmt_in.video.i_width;
115     p_sys->param.i_height = p_enc->fmt_in.video.i_height;
116     p_sys->param.i_idrframe = 1;
117     if( p_enc->i_iframes > 0 )
118     {
119         p_sys->param.i_iframe = p_enc->i_iframes;
120     }
121     var_Get( p_enc, SOUT_CFG_PREFIX "qp", &val );
122     if( val.i_int >= 1 && val.i_int <= 51 )
123     {
124         p_sys->param.i_qp_constant = val.i_int;
125     }
126
127     var_Get( p_enc, SOUT_CFG_PREFIX "cabac", &val );
128     p_sys->param.b_cabac = val.b_bool;
129
130     var_Get( p_enc, SOUT_CFG_PREFIX "loopfilter", &val );
131     p_sys->param.b_deblocking_filter = val.b_bool;
132
133     if( p_enc->fmt_in.video.i_aspect > 0 )
134     {
135         p_sys->param.vui.i_sar_width = p_enc->fmt_in.video.i_aspect *
136                                        p_enc->fmt_in.video.i_height *
137                                        p_enc->fmt_in.video.i_height /
138                                        p_enc->fmt_in.video.i_width;
139         p_sys->param.vui.i_sar_height = p_enc->fmt_in.video.i_height;
140     }
141     if( p_enc->fmt_in.video.i_frame_rate_base > 0 )
142     {
143         p_sys->param.f_fps = (float)p_enc->fmt_in.video.i_frame_rate /
144                              (float)p_enc->fmt_in.video.i_frame_rate_base;
145     }
146     if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_MMX) )
147     {
148         p_sys->param.cpu &= ~X264_CPU_MMX;
149     }
150     if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_MMXEXT) )
151     {
152         p_sys->param.cpu &= ~X264_CPU_MMXEXT;
153     }
154     if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_SSE) )
155     {
156         p_sys->param.cpu &= ~(X264_CPU_SSE|X264_CPU_SSE2);
157     }
158
159     p_sys->param.analyse.inter = X264_ANALYSE_I16x16 | X264_ANALYSE_I4x4  |
160                                  X264_ANALYSE_P16x16 |
161                                  X264_ANALYSE_P16x8 | X264_ANALYSE_P8x16 |
162                                  X264_ANALYSE_P8x8 | X264_ANALYSE_SMART_PSUB;
163
164     var_Get( p_enc, SOUT_CFG_PREFIX "analyse", &val );
165     if( !strcmp( val.psz_string, "none" ) )
166     {
167         p_sys->param.analyse.inter = 0;
168     }
169     else if( !strcmp( val.psz_string, "fastest" ) )
170     {
171         p_sys->param.analyse.inter = X264_ANALYSE_I16x16 | X264_ANALYSE_P16x16;
172     }
173     else if( !strcmp( val.psz_string, "fast" ) )
174     {
175         p_sys->param.analyse.inter = X264_ANALYSE_I16x16 | X264_ANALYSE_I4x4 |
176                                      X264_ANALYSE_P16x16 |
177                                      X264_ANALYSE_P16x8 | X264_ANALYSE_P8x16 |
178                                      X264_ANALYSE_SMART_PSUB;
179     }
180     else if( !strcmp( val.psz_string, "normal" ) )
181     {
182         p_sys->param.analyse.inter = X264_ANALYSE_I16x16 | X264_ANALYSE_I4x4 |
183                                      X264_ANALYSE_P16x16 |
184                                      X264_ANALYSE_P16x8 | X264_ANALYSE_P8x16 |
185                                      X264_ANALYSE_P8x8 |
186                                      X264_ANALYSE_SMART_PSUB;
187     }
188     else if( !strcmp( val.psz_string, "slow" ) )
189     {
190         p_sys->param.analyse.inter = X264_ANALYSE_I16x16 | X264_ANALYSE_I4x4 |
191                                      X264_ANALYSE_P16x16 | X264_ANALYSE_P16x8 |
192                                      X264_ANALYSE_P8x16 | X264_ANALYSE_P8x8 |
193                                      X264_ANALYSE_P8x4 | X264_ANALYSE_P4x8 |
194                                      X264_ANALYSE_SMART_PSUB;
195     }
196     else if( !strcmp( val.psz_string, "slowest" ) )
197     {
198         p_sys->param.analyse.inter = X264_ANALYSE_I16x16 | X264_ANALYSE_I4x4 |
199                                      X264_ANALYSE_P16x16 | X264_ANALYSE_P16x8 |
200                                      X264_ANALYSE_P8x16 | X264_ANALYSE_P8x8 |
201                                      X264_ANALYSE_P8x4 | X264_ANALYSE_P4x8 |
202                                      X264_ANALYSE_P4x4 |
203                                      X264_ANALYSE_SMART_PSUB;
204     }
205     else if( !strcmp( val.psz_string, "all" ) )
206     {
207         p_sys->param.analyse.inter = X264_ANALYSE_I16x16 | X264_ANALYSE_I4x4 |
208                                      X264_ANALYSE_P16x16 | X264_ANALYSE_P16x8 |
209                                      X264_ANALYSE_P8x16 | X264_ANALYSE_P8x8 |
210                                      X264_ANALYSE_P8x4 | X264_ANALYSE_P4x8 |
211                                      X264_ANALYSE_P4x4;
212     }
213
214     /* Open the encoder */
215     p_sys->h = x264_encoder_open( &p_sys->param );
216
217     /* alloc mem */
218     p_sys->pic      = x264_picture_new( p_sys->h );
219     p_sys->i_buffer = 4 * p_enc->fmt_in.video.i_width * p_enc->fmt_in.video.i_height + 1000;
220     p_sys->p_buffer = malloc( p_sys->i_buffer );
221
222     /* get the globals headers */
223     p_enc->fmt_out.i_extra = 0;
224     p_enc->fmt_out.p_extra = NULL;
225
226 #if 0
227     x264_encoder_headers( p_sys->h, &nal, &i_nal );
228     for( i = 0; i < i_nal; i++ )
229     {
230         int i_size = p_sys->i_buffer;
231
232         x264_nal_encode( p_sys->p_buffer, &i_size, 1, &nal[i] );
233
234         p_enc->fmt_out.p_extra = realloc( p_enc->fmt_out.p_extra, p_enc->fmt_out.i_extra + i_size );
235
236         memcpy( p_enc->fmt_out.p_extra + p_enc->fmt_out.i_extra,
237                 p_sys->p_buffer, i_size );
238
239         p_enc->fmt_out.i_extra += i_size;
240     }
241 #endif
242
243     return VLC_SUCCESS;
244 }
245
246 /****************************************************************************
247  * Encode:
248  ****************************************************************************/
249 static block_t *Encode( encoder_t *p_enc, picture_t *p_pict )
250 {
251     encoder_sys_t *p_sys = p_enc->p_sys;
252     int        i_nal;
253     x264_nal_t *nal;
254     block_t *p_block;
255     int i_out;
256     int i;
257
258     /* copy the picture */
259     for( i = 0; i < 3; i++ )
260     {
261         uint8_t *src = p_pict->p[i].p_pixels;
262         uint8_t *dst = p_sys->pic->plane[i];
263         int j;
264
265         for( j = 0;j < p_pict->p[i].i_lines; j++ )
266         {
267             memcpy( dst, src, __MIN( p_sys->pic->i_stride[i], p_pict->p[i].i_pitch ) );
268
269             src += p_pict->p[i].i_pitch;
270             dst += p_sys->pic->i_stride[i];
271         }
272     }
273
274     x264_encoder_encode( p_sys->h, &nal, &i_nal, p_sys->pic );
275     for( i = 0, i_out = 0; i < i_nal; i++ )
276     {
277         int i_size = p_sys->i_buffer - i_out;
278         x264_nal_encode( p_sys->p_buffer + i_out, &i_size, 1, &nal[i] );
279
280         i_out += i_size;
281     }
282
283     p_block = block_New( p_enc, i_out );
284     p_block->i_dts = p_pict->date;
285     p_block->i_pts = p_pict->date;
286     memcpy( p_block->p_buffer, p_sys->p_buffer, i_out );
287
288     /* TODO */
289     /* p_block->i_flags |= BLOCK_FLAG_TYPE_I; */
290
291     return p_block;
292 }
293
294 /*****************************************************************************
295  * CloseEncoder: ffmpeg encoder destruction
296  *****************************************************************************/
297 static void Close( vlc_object_t *p_this )
298 {
299     encoder_t     *p_enc = (encoder_t *)p_this;
300     encoder_sys_t *p_sys = p_enc->p_sys;
301
302
303     x264_picture_delete( p_sys->pic );
304     x264_encoder_close( p_sys->h );
305     free( p_sys->p_buffer );
306     free( p_sys );
307 }