comparison libmpcodecs/ve_x264.c @ 13166:d198f255bee9

x264 encoder support. Original patch send by Bernhard Rosenkraenzer <bero at arklinux dot org>, modifications by Loren Merritt <lorenm at u.washington dot edu>, Jeff Clagg <snacky at ikaruga.co dot uk> and me
author iive
date Fri, 27 Aug 2004 20:43:05 +0000
parents
children f26d2c9aec04
comparison
equal deleted inserted replaced
13165:3925db29cf1e 13166:d198f255bee9
1 /*****************************************************************************
2 *
3 * - H.264 encoder for mencoder using x264 -
4 *
5 * Copyright (C) 2004 LINUX4MEDIA GmbH
6 * Copyright (C) 2004 Ark Linux
7 *
8 * Written by Bernhard Rosenkraenzer <bero@arklinux.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation, or if, and only if,
13 * version 2 is ruled invalid in a court of law, any later version
14 * of the GNU General Public License published by the Free Software
15 * Foundation.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 *****************************************************************************/
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <stdint.h>
33
34 #include "../config.h"
35 #include "../mp_msg.h"
36
37 #ifdef HAVE_X264
38
39 #include "m_option.h"
40 #include "codec-cfg.h"
41 #include "stream.h"
42 #include "demuxer.h"
43 #include "stheader.h"
44
45 #include "muxer.h"
46
47 #include "img_format.h"
48 #include "mp_image.h"
49 #include "vf.h"
50
51 #include <x264.h>
52
53 typedef struct _h264_module_t {
54 muxer_stream_t *mux;
55 x264_param_t param;
56 x264_t * x264;
57 x264_picture_t pic;
58 } h264_module_t;
59
60 extern char* passtmpfile;
61
62 static int bitrate = -1;
63 static int qp_constant = 26;
64 static int frame_ref = 1;
65 static int iframe = 60;
66 static int idrframe = 2;
67 static int bframe = 0;
68 static int deblock = 1;
69 static int deblockalpha = 0;
70 static int deblockbeta = 0;
71 static int cabac = 0;
72 static int cabacidc = -1;
73 static int fullinter = 0;
74 static float ip_factor = 2.0;
75 static float pb_factor = 2.0;
76 static int rc_buffer_size = -1;
77 static int rc_init_buffer = -1;
78 static int rc_sens = 4;
79 static int qp_min = 10;
80 static int qp_max = 51;
81 static int qp_step = 1;
82 static int pass = 0;
83 static float qcomp = 0.6;
84 static float qblur = 0.5;
85 static char *rc_eq = "(tex^qComp)*(avgTex^(1-qComp))";
86 static int psnr = 0;
87 static int log_level = 2;
88
89 m_option_t x264encopts_conf[] = {
90 {"bitrate", &bitrate, CONF_TYPE_INT, CONF_RANGE, 0, 24000000, NULL},
91 {"qp_constant", &qp_constant, CONF_TYPE_INT, CONF_RANGE, 1, 51, NULL},
92 {"frameref", &frame_ref, CONF_TYPE_INT, CONF_RANGE, 1, 100, NULL},
93 {"iframe", &iframe, CONF_TYPE_INT, CONF_RANGE, 1, 24000000, NULL},
94 {"idrframe", &idrframe, CONF_TYPE_INT, CONF_RANGE, 1, 24000000, NULL},
95 {"bframe", &bframe, CONF_TYPE_INT, CONF_RANGE, 0, 10, NULL},
96 {"deblock", &deblock, CONF_TYPE_INT, CONF_RANGE, 0, 1, NULL},
97 {"deblockalpha", &deblockalpha, CONF_TYPE_INT, CONF_RANGE, -6, 6, NULL},
98 {"deblockbeta", &deblockbeta, CONF_TYPE_INT, CONF_RANGE, -6, 6, NULL},
99 {"cabac", &cabac, CONF_TYPE_FLAG, 0, 0, 1, NULL},
100 {"cabacidc", &cabacidc, CONF_TYPE_INT, CONF_RANGE, -1, 2, NULL},
101 {"fullinter", &fullinter, CONF_TYPE_FLAG, 0, 0, 1, NULL},
102 {"ip_factor", &ip_factor, CONF_TYPE_FLOAT, CONF_RANGE, -10.0, 10.0, NULL},
103 {"pb_factor", &pb_factor, CONF_TYPE_FLOAT, CONF_RANGE, -10.0, 10.0, NULL},
104 {"rc_buffer_size", &rc_buffer_size, CONF_TYPE_INT, CONF_RANGE, 0, 24000000, NULL},
105 {"rc_init_buffer", &rc_init_buffer, CONF_TYPE_INT, CONF_RANGE, 0, 24000000, NULL},
106 {"rc_sens", &rc_sens, CONF_TYPE_INT, CONF_RANGE, 0, 100, NULL},
107 {"qp_min", &qp_min, CONF_TYPE_INT, CONF_RANGE, 1, 51, NULL},
108 {"qp_max", &qp_max, CONF_TYPE_INT, CONF_RANGE, 1, 51, NULL},
109 {"qp_step", &qp_step, CONF_TYPE_INT, CONF_RANGE, 0, 50, NULL},
110 {"pass", &pass, CONF_TYPE_INT, CONF_RANGE, 1, 3, NULL},
111 {"rc_eq", &rc_eq, CONF_TYPE_STRING, 0, 0, 0, NULL},
112 {"qcomp", &qcomp, CONF_TYPE_FLOAT, CONF_RANGE, 0, 1, NULL},
113 {"qblur", &qblur, CONF_TYPE_FLOAT, CONF_RANGE, 0, 99, NULL},
114 {"psnr", &psnr, CONF_TYPE_FLAG, 0, 0, 1, NULL},
115 {"log", &log_level, CONF_TYPE_INT, CONF_RANGE, -1, 3, NULL},
116 {NULL, NULL, 0, 0, 0, 0, NULL}
117 };
118
119
120 static int config(struct vf_instance_s* vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt) {
121 h264_module_t *mod=(h264_module_t*)vf->priv;
122 mod->mux->bih->biWidth = width;
123 mod->mux->bih->biHeight = height;
124 mod->mux->aspect = (float)d_width/d_height;
125
126 x264_param_default(&mod->param);
127 mod->param.i_frame_reference = frame_ref;
128 mod->param.i_idrframe = idrframe;
129 mod->param.i_iframe = iframe;
130 mod->param.i_bframe = bframe;
131 mod->param.b_deblocking_filter = deblock;
132 mod->param.i_deblocking_filter_alphac0 = deblockalpha;
133 mod->param.i_deblocking_filter_beta = deblockbeta;
134 mod->param.b_cabac = cabac;
135 mod->param.i_cabac_init_idc = cabacidc;
136 mod->param.i_qp_constant = qp_constant;
137 if(qp_min > qp_constant)
138 qp_min = qp_constant;
139 if(qp_max < qp_constant)
140 qp_max = qp_constant;
141 mod->param.i_qp_min = qp_min;
142 mod->param.i_qp_max = qp_max;
143 mod->param.i_qp_step = qp_step;
144 #if 0
145 mod->param.i_pass = pass;
146 mod->param.s_rc_eq = rc_eq;
147 mod->param.f_qcompress = qcomp;
148 mod->param.f_qblur = qblur;
149 mod->param.s_2pass_file_out = passtmpfile;
150 mod->param.s_2pass_file_in = passtmpfile;
151 if((pass & 2) && bitrate <= 0)
152 {
153 mp_msg(MSGT_MENCODER, MSGL_ERR,
154 "2 pass encoding enabled, but no bitrate specified.\n");
155 return 0;
156 }
157 #endif
158 if(bitrate > 0) {
159 if(rc_buffer_size <= 0)
160 rc_buffer_size = bitrate;
161 if(rc_init_buffer < 0)
162 rc_init_buffer = rc_buffer_size/4;
163 mod->param.b_cbr = 1;
164 mod->param.i_bitrate = bitrate;
165 mod->param.i_rc_buffer_size = rc_buffer_size;
166 mod->param.i_rc_init_buffer = rc_init_buffer;
167 mod->param.i_rc_sens = rc_sens;
168 }
169 if(fullinter)
170 mod->param.analyse.inter = X264_ANALYSE_I4x4 | X264_ANALYSE_PSUB16x16 | X264_ANALYSE_PSUB8x8;
171 mod->param.f_ip_factor = ip_factor;
172 mod->param.f_pb_factor = pb_factor;
173
174 mod->param.i_width = width;
175 mod->param.i_height = height;
176 mod->param.i_fps_num = mod->mux->h.dwRate;
177 mod->param.i_fps_den = mod->mux->h.dwScale;
178 mod->param.analyse.b_psnr = psnr;
179 mod->param.i_log_level = log_level;
180
181 switch(outfmt) {
182 case IMGFMT_I420:
183 mod->param.i_csp = X264_CSP_I420;
184 mod->mux->bih->biSizeImage = width * height * 3;
185 break;
186 case IMGFMT_YV12:
187 mod->param.i_csp = X264_CSP_YV12;
188 mod->mux->bih->biSizeImage = width * height * 3;
189 break;
190 case IMGFMT_422P:
191 mod->param.i_csp = X264_CSP_I422;
192 mod->mux->bih->biSizeImage = width * height * 3;
193 break;
194 case IMGFMT_444P:
195 mod->param.i_csp = X264_CSP_I444;
196 mod->mux->bih->biSizeImage = width * height * 3;
197 break;
198 case IMGFMT_YVYU:
199 mod->param.i_csp = X264_CSP_YUYV;
200 mod->mux->bih->biSizeImage = width * height * 3;
201 break;
202 case IMGFMT_RGB:
203 mod->param.i_csp = X264_CSP_RGB;
204 mod->mux->bih->biSizeImage = width * height * 3;
205 break;
206 case IMGFMT_BGR:
207 mod->param.i_csp = X264_CSP_BGR;
208 mod->mux->bih->biSizeImage = width * height * 3;
209 break;
210 case IMGFMT_BGR32:
211 mod->param.i_csp = X264_CSP_BGRA;
212 mod->mux->bih->biSizeImage = width * height * 4;
213 break;
214 default:
215 mp_msg(MSGT_MENCODER, MSGL_ERR, "Wrong colorspace.\n");
216 return 0;
217 }
218
219 mod->x264 = x264_encoder_open(&mod->param);
220 if(!mod->x264) {
221 mp_msg(MSGT_MENCODER, MSGL_ERR, "x264_encoder_open failed.\n");
222 return 0;
223 }
224
225 x264_picture_alloc(&mod->pic, mod->param.i_csp, mod->param.i_width, mod->param.i_height);
226 return 1;
227 }
228
229 static int control(struct vf_instance_s* vf, int request, void *data)
230 {
231 return CONTROL_UNKNOWN;
232 }
233
234 static int query_format(struct vf_instance_s* vf, unsigned int fmt)
235 {
236 switch(fmt) {
237 case IMGFMT_I420:
238 return (VFCAP_CSP_SUPPORTED|VFCAP_CSP_SUPPORTED_BY_HW);
239 case IMGFMT_YV12:
240 case IMGFMT_422P:
241 case IMGFMT_444P:
242 case IMGFMT_YVYU:
243 case IMGFMT_RGB:
244 case IMGFMT_BGR:
245 case IMGFMT_BGR32:
246 /* 2004/08/05: There seems to be some, but not complete,
247 support for these colorspaces in X264. Better to stay
248 on the safe side for now. */
249 return 0; /* VFCAP_CSP_SUPPORTED */
250 }
251 return 0;
252 }
253
254 static int put_image(struct vf_instance_s *vf, mp_image_t *mpi)
255 {
256 h264_module_t *mod=(h264_module_t*)vf->priv;
257 int i_nal;
258 x264_nal_t *nal;
259 int i;
260
261 int csp=mod->pic.img.i_csp;
262 memset(&mod->pic, 0, sizeof(x264_picture_t));
263 mod->pic.img.i_csp=csp;
264 mod->pic.img.i_plane=3;
265 for(i=0; i<4; i++) {
266 mod->pic.img.plane[i] = mpi->planes[i];
267 mod->pic.img.i_stride[i] = mpi->stride[i];
268 }
269
270 mod->pic.i_type = X264_TYPE_AUTO;
271 if(x264_encoder_encode(mod->x264, &nal, &i_nal, &mod->pic) < 0) {
272 mp_msg(MSGT_MENCODER, MSGL_ERR, "x264_encoder_encode failed\n");
273 return 0;
274 }
275
276 int i_size = 0;
277 for(i=0; i < i_nal; i++) {
278 int i_data = mod->mux->buffer_size - i_size;
279 i_size += x264_nal_encode(mod->mux->buffer + i_size, &i_data, 1, &nal[i]);
280 }
281 if(i_size>0) {
282 muxer_write_chunk(mod->mux, i_size, (mod->pic.i_type == X264_TYPE_I)?0x10:0);
283 }
284 return 1;
285 }
286
287 static void uninit(struct vf_instance_s *vf)
288 {
289 // FIXME: flush delayed frames
290 h264_module_t *mod=(h264_module_t*)vf->priv;
291 x264_encoder_close(mod->x264);
292 //x264_picture_clean(&mod->pic);
293 }
294
295 static int vf_open(vf_instance_t *vf, char *args) {
296 vf->config = config;
297 vf->control = control;
298 vf->query_format = query_format;
299 vf->put_image = put_image;
300 vf->uninit = uninit;
301 vf->priv = malloc(sizeof(h264_module_t));
302
303 h264_module_t *mod=(h264_module_t*)vf->priv;
304 mod->mux = (muxer_stream_t*)args;
305 mod->mux->bih = malloc(sizeof(BITMAPINFOHEADER));
306 memset(mod->mux->bih, 0, sizeof(BITMAPINFOHEADER));
307 mod->mux->bih->biSize = sizeof(BITMAPINFOHEADER);
308 mod->mux->bih->biPlanes = 1;
309 mod->mux->bih->biBitCount = 24;
310 mod->mux->bih->biCompression = mmioFOURCC('h', '2', '6', '4');
311
312 return 1;
313 }
314
315 vf_info_t ve_info_x264 = {
316 "H.264 encoder",
317 "x264",
318 "Bernhard Rosenkraenzer <bero@arklinux.org>",
319 "(C) 2004 LINUX4MEDIA GmbH; (C) 2004 Ark Linux",
320 vf_open
321 };
322 #endif