]> git.sesse.net Git - vlc/blob - modules/codec/x264.c
* x264: added aspect support.
[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/decoder.h>
30
31 #include <x264.h>
32
33 /*****************************************************************************
34  * Module descriptor
35  *****************************************************************************/
36 static int  Open ( vlc_object_t * );
37 static void Close( vlc_object_t * );
38
39 vlc_module_begin();
40     set_description( _("h264 video encoder using x264 library"));
41     set_capability( "encoder", 200 );
42     set_callbacks( Open, Close );
43 vlc_module_end();
44
45
46 /*****************************************************************************
47  * Local prototypes
48  *****************************************************************************/
49 static block_t *Encode( encoder_t *, picture_t * );
50
51 struct encoder_sys_t
52 {
53     x264_t          *h;
54     x264_param_t    param;
55     x264_picture_t  *pic;
56
57     int             i_buffer;
58     uint8_t         *p_buffer;
59 };
60
61 /*****************************************************************************
62  * Open: probe the encoder
63  *****************************************************************************/
64 static int  Open ( vlc_object_t *p_this )
65 {
66     encoder_t     *p_enc = (encoder_t *)p_this;
67     encoder_sys_t *p_sys;
68     int           i_nal;
69     x264_nal_t    *nal;
70
71     int i;
72
73     if( p_enc->fmt_out.i_cat != VIDEO_ES ||
74         p_enc->fmt_out.i_codec != VLC_FOURCC( 'h', '2', '6', '4' ) )
75     {
76         return VLC_EGENERIC;
77     }
78     if( p_enc->fmt_in.video.i_width % 16 != 0 ||
79         p_enc->fmt_in.video.i_height % 16!= 0 )
80     {
81         msg_Warn( p_enc, "invalid size %ix%i",
82                   p_enc->fmt_in.video.i_width,
83                   p_enc->fmt_in.video.i_height );
84         return VLC_EGENERIC;
85     }
86
87     p_enc->pf_encode_video = Encode;
88     p_enc->pf_encode_audio = NULL;
89     p_enc->p_sys = p_sys = malloc( sizeof( encoder_sys_t ) );
90
91     x264_param_default( &p_sys->param );
92     p_sys->param.i_width  = p_enc->fmt_in.video.i_width;
93     p_sys->param.i_height = p_enc->fmt_in.video.i_height;
94     p_sys->param.analyse.inter = X264_ANALYSE_I16x16 | X264_ANALYSE_I4x4  |
95                                  X264_ANALYSE_P16x16 |
96                                  X264_ANALYSE_P16x8 | X264_ANALYSE_P8x16 |
97                                  X264_ANALYSE_P8x8 | X264_ANALYSE_SMART_PSUB;
98     p_sys->param.i_idrframe = 1;
99     p_sys->param.b_cabac = 1;
100
101     if( p_enc->fmt_in.video.i_aspect > 0 )
102     {
103         p_sys->param.vui.i_sar_width = p_enc->fmt_in.video.i_aspect *
104                                        p_enc->fmt_in.video.i_height *
105                                        p_enc->fmt_in.video.i_height /
106                                        p_enc->fmt_in.video.i_width;
107         p_sys->param.vui.i_sar_height = p_enc->fmt_in.video.i_height;
108     }
109     if( p_enc->fmt_in.video.i_frame_rate_base > 0 )
110     {
111         p_sys->param.f_fps = (float)p_enc->fmt_in.video.i_frame_rate /
112                              (float)p_enc->fmt_in.video.i_frame_rate_base;
113     }
114     if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_MMX) )
115     {
116         p_sys->param.cpu &= ~X264_CPU_MMX;
117     }
118     if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_MMXEXT) )
119     {
120         p_sys->param.cpu &= ~X264_CPU_MMXEXT;
121     }
122     if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_SSE) )
123     {
124         p_sys->param.cpu &= ~(X264_CPU_SSE|X264_CPU_SSE2);
125     }
126     if( p_enc->i_key_int > 0 )
127     {
128         p_sys->param.i_iframe = p_enc->i_key_int;
129     }
130
131     p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','0');
132     if( p_enc->i_qmin == p_enc->i_qmax )
133     {
134         p_sys->param.i_qp_constant = p_enc->i_qmin;
135     }
136     switch( p_enc->i_hq )
137     {
138         case -1:
139             p_sys->param.analyse.inter = 0;
140             break;
141         case -2:
142             p_sys->param.analyse.inter = X264_ANALYSE_I16x16|X264_ANALYSE_I4x4|X264_ANALYSE_P16x16;
143             break;
144         case -3:
145             p_sys->param.analyse.inter = X264_ANALYSE_I16x16|X264_ANALYSE_I4x4|X264_ANALYSE_P16x16|
146                                          X264_ANALYSE_P16x8|X264_ANALYSE_P8x16|X264_ANALYSE_P8x8|X264_ANALYSE_SMART_PSUB;
147             break;
148         case -4:
149             p_sys->param.analyse.inter = X264_ANALYSE_I16x16|X264_ANALYSE_I4x4|X264_ANALYSE_P16x16|
150                                          X264_ANALYSE_P16x8|X264_ANALYSE_P8x16|X264_ANALYSE_P8x8|
151                                          X264_ANALYSE_P8x4|X264_ANALYSE_P4x8|X264_ANALYSE_P4x4|
152                                          X264_ANALYSE_SMART_PSUB;
153             break;
154     }
155
156     /* Open the encoder */
157     p_sys->h = x264_encoder_open( &p_sys->param );
158
159     /* alloc mem */
160     p_sys->pic      = x264_picture_new( p_sys->h );
161     p_sys->i_buffer = 4 * p_enc->fmt_in.video.i_width * p_enc->fmt_in.video.i_height + 1000;
162     p_sys->p_buffer = malloc( p_sys->i_buffer );
163
164     /* get the globals headers */
165     p_enc->fmt_out.i_extra = 0;
166     p_enc->fmt_out.p_extra = NULL;
167 #if 0
168     x264_encoder_headers( p_sys->h, &nal, &i_nal );
169     for( i = 0; i < i_nal; i++ )
170     {
171         int i_size = p_sys->i_buffer;
172
173         x264_nal_encode( p_sys->p_buffer, &i_size, 1, &nal[i] );
174
175         p_enc->fmt_out.p_extra = realloc( p_enc->fmt_out.p_extra, p_enc->fmt_out.i_extra + i_size );
176
177         memcpy( p_enc->fmt_out.p_extra + p_enc->fmt_out.i_extra,
178                 p_sys->p_buffer, i_size );
179
180         p_enc->fmt_out.i_extra += i_size;
181     }
182 #endif
183
184     return VLC_SUCCESS;
185 }
186
187 /****************************************************************************
188  * Encode:
189  ****************************************************************************/
190 static block_t *Encode( encoder_t *p_enc, picture_t *p_pict )
191 {
192     encoder_sys_t *p_sys = p_enc->p_sys;
193     int        i_nal;
194     x264_nal_t *nal;
195     block_t *p_block;
196     int i_out;
197     int i;
198
199     /* copy the picture */
200     for( i = 0; i < 3; i++ )
201     {
202         uint8_t *src = p_pict->p[i].p_pixels;
203         uint8_t *dst = p_sys->pic->plane[i];
204         int j;
205
206         for( j = 0;j < p_pict->p[i].i_lines; j++ )
207         {
208             memcpy( dst, src, __MIN( p_sys->pic->i_stride[i], p_pict->p[i].i_pitch ) );
209
210             src += p_pict->p[i].i_pitch;
211             dst += p_sys->pic->i_stride[i];
212         }
213     }
214
215     x264_encoder_encode( p_sys->h, &nal, &i_nal, p_sys->pic );
216     for( i = 0, i_out = 0; i < i_nal; i++ )
217     {
218         int i_size = p_sys->i_buffer - i_out;
219         x264_nal_encode( p_sys->p_buffer + i_out, &i_size, 1, &nal[i] );
220
221         i_out += i_size;
222     }
223
224     p_block = block_New( p_enc, i_out );
225     p_block->i_dts = p_pict->date;
226     p_block->i_pts = p_pict->date;
227     memcpy( p_block->p_buffer, p_sys->p_buffer, i_out );
228
229     /* TODO */
230     /* p_block->i_flags |= BLOCK_FLAG_TYPE_I; */
231
232     return p_block;
233 }
234
235 /*****************************************************************************
236  * CloseEncoder: ffmpeg encoder destruction
237  *****************************************************************************/
238 static void Close( vlc_object_t *p_this )
239 {
240     encoder_t     *p_enc = (encoder_t *)p_this;
241     encoder_sys_t *p_sys = p_enc->p_sys;
242
243
244     x264_picture_delete( p_sys->pic );
245     x264_encoder_close( p_sys->h );
246     free( p_sys->p_buffer );
247     free( p_sys );
248 }