1 /*****************************************************************************
3 * - H.264 encoder for mencoder using x264 -
5 * Copyright (C) 2004 LINUX4MEDIA GmbH
6 * Copyright (C) 2004 Ark Linux
8 * Written by Bernhard Rosenkraenzer <bero@arklinux.org>
10 * This file is part of MPlayer.
12 * MPlayer is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * MPlayer is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 *****************************************************************************/
37 #include "codec-cfg.h"
38 #include "stream/stream.h"
39 #include "libmpdemux/demuxer.h"
40 #include "libmpdemux/stheader.h"
42 #include "stream/stream.h"
43 #include "libmpdemux/muxer.h"
45 #include "img_format.h"
52 typedef struct h264_module_t
{
58 extern char* passtmpfile
;
60 static x264_param_t param
;
61 static int parse_error
= 0;
63 static int put_image(struct vf_instance
*vf
, mp_image_t
*mpi
, double pts
);
64 static int encode_frame(struct vf_instance
*vf
, x264_picture_t
*pic_in
);
66 void x264enc_set_param(const m_option_t
* opt
, char* arg
)
68 static int initted
= 0;
70 x264_param_default(¶m
);
71 x264_param_parse(¶m
, "psnr", "no");
72 x264_param_parse(¶m
, "ssim", "no");
86 arg
+= strcspn(arg
, ":");
92 value
= strchr( name
, '=' );
98 if(!strcmp(name
, "turbo")) {
99 turbo
= value
? atoi(value
) : 1;
103 ret
= x264_param_parse(¶m
, name
, value
);
104 if(ret
== X264_PARAM_BAD_NAME
)
105 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Option x264encopts: Unknown suboption %s\n", name
);
106 if(ret
== X264_PARAM_BAD_VALUE
)
107 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Option x264encopts: Bad argument %s=%s\n", name
, value
? value
: "(null)");
109 /* mark this option as done, so it's not reparsed if there's another -x264encopts */
115 if(param
.rc
.b_stat_write
&& !param
.rc
.b_stat_read
) {
116 /* Adjust or disable some flags to gain speed in the first pass */
119 param
.i_frame_reference
= ( param
.i_frame_reference
+ 1 ) >> 1;
120 param
.analyse
.i_subpel_refine
= FFMAX( FFMIN( 3, param
.analyse
.i_subpel_refine
- 1 ), 1 );
121 param
.analyse
.inter
&= ( ~X264_ANALYSE_PSUB8x8
);
122 param
.analyse
.inter
&= ( ~X264_ANALYSE_BSUB16x16
);
123 param
.analyse
.i_trellis
= 0;
127 param
.i_frame_reference
= 1;
128 param
.analyse
.i_subpel_refine
= 1;
129 param
.analyse
.i_me_method
= X264_ME_DIA
;
130 param
.analyse
.inter
= 0;
131 param
.analyse
.b_transform_8x8
= 0;
132 param
.analyse
.b_weighted_bipred
= 0;
133 param
.analyse
.i_trellis
= 0;
138 static int config(struct vf_instance
*vf
, int width
, int height
, int d_width
, int d_height
, unsigned int flags
, unsigned int outfmt
) {
139 h264_module_t
*mod
=(h264_module_t
*)vf
->priv
;
144 mod
->mux
->bih
->biWidth
= width
;
145 mod
->mux
->bih
->biHeight
= height
;
146 mod
->mux
->bih
->biSizeImage
= width
* height
* 3;
147 mod
->mux
->aspect
= (float)d_width
/d_height
;
149 // make sure param is initialized
150 x264enc_set_param(NULL
, "");
151 param
.i_width
= width
;
152 param
.i_height
= height
;
153 param
.i_fps_num
= mod
->mux
->h
.dwRate
;
154 param
.i_fps_den
= mod
->mux
->h
.dwScale
;
155 param
.b_vfr_input
= 0;
156 param
.vui
.i_sar_width
= d_width
*height
;
157 param
.vui
.i_sar_height
= d_height
*width
;
159 x264_param_parse(¶m
, "stats", passtmpfile
);
163 param
.i_csp
= X264_CSP_I420
;
166 param
.i_csp
= X264_CSP_YV12
;
169 mp_msg(MSGT_MENCODER
, MSGL_ERR
, "Wrong colorspace.\n");
173 mod
->x264
= x264_encoder_open(¶m
);
175 mp_msg(MSGT_MENCODER
, MSGL_ERR
, "x264_encoder_open failed.\n");
179 if(!param
.b_repeat_headers
){
181 int extradata_size
, nnal
;
183 extradata_size
= x264_encoder_headers(mod
->x264
, &nal
, &nnal
);
185 mod
->mux
->bih
= realloc(mod
->mux
->bih
, sizeof(BITMAPINFOHEADER
) + extradata_size
);
186 memcpy(mod
->mux
->bih
+ 1, nal
->p_payload
, extradata_size
);
187 mod
->mux
->bih
->biSize
= sizeof(BITMAPINFOHEADER
) + extradata_size
;
190 if (param
.i_bframe
> 1 && param
.i_bframe_pyramid
)
191 mod
->mux
->decoder_delay
= 2;
193 mod
->mux
->decoder_delay
= param
.i_bframe
? 1 : 0;
198 static int control(struct vf_instance
*vf
, int request
, void *data
)
200 h264_module_t
*mod
=(h264_module_t
*)vf
->priv
;
202 case VFCTRL_FLUSH_FRAMES
:
203 while (x264_encoder_delayed_frames(mod
->x264
) > 0)
204 encode_frame(vf
, NULL
);
207 return CONTROL_UNKNOWN
;
211 static int query_format(struct vf_instance
*vf
, unsigned int fmt
)
215 return VFCAP_CSP_SUPPORTED
| VFCAP_CSP_SUPPORTED_BY_HW
;
223 /* These colorspaces are supported, but they'll just have
224 * to be converted to I420 internally */
225 return 0; /* VFCAP_CSP_SUPPORTED */
230 static int put_image(struct vf_instance
*vf
, mp_image_t
*mpi
, double pts
)
232 h264_module_t
*mod
=(h264_module_t
*)vf
->priv
;
235 memset(&mod
->pic
, 0, sizeof(x264_picture_t
));
236 mod
->pic
.img
.i_csp
=param
.i_csp
;
237 mod
->pic
.img
.i_plane
=3;
239 mod
->pic
.img
.plane
[i
] = mpi
->planes
[i
];
240 mod
->pic
.img
.i_stride
[i
] = mpi
->stride
[i
];
243 mod
->pic
.i_type
= X264_TYPE_AUTO
;
245 return encode_frame(vf
, &mod
->pic
) >= 0;
248 static int encode_frame(struct vf_instance
*vf
, x264_picture_t
*pic_in
)
250 h264_module_t
*mod
=(h264_module_t
*)vf
->priv
;
251 x264_picture_t pic_out
;
256 i_size
= x264_encoder_encode(mod
->x264
, &nal
, &i_nal
, pic_in
, &pic_out
);
259 mp_msg(MSGT_MENCODER
, MSGL_ERR
, "x264_encoder_encode failed\n");
263 int keyframe
= pic_out
.b_keyframe
;
264 memcpy(mod
->mux
->buffer
, nal
->p_payload
, i_size
);
265 muxer_write_chunk(mod
->mux
, i_size
, keyframe
?AVIIF_KEYFRAME
:0, MP_NOPTS_VALUE
, MP_NOPTS_VALUE
);
268 ++mod
->mux
->encoder_delay
;
273 static void uninit(struct vf_instance
*vf
)
275 h264_module_t
*mod
=(h264_module_t
*)vf
->priv
;
277 x264_encoder_close(mod
->x264
);
280 static int vf_open(vf_instance_t
*vf
, char *args
) {
284 vf
->default_caps
= VFCAP_CONSTANT
;
285 vf
->control
= control
;
286 vf
->query_format
= query_format
;
287 vf
->put_image
= put_image
;
289 vf
->priv
= malloc(sizeof(h264_module_t
));
291 mod
=(h264_module_t
*)vf
->priv
;
292 mod
->mux
= (muxer_stream_t
*)args
;
293 mod
->mux
->bih
= malloc(sizeof(BITMAPINFOHEADER
));
294 memset(mod
->mux
->bih
, 0, sizeof(BITMAPINFOHEADER
));
295 mod
->mux
->bih
->biSize
= sizeof(BITMAPINFOHEADER
);
296 mod
->mux
->bih
->biPlanes
= 1;
297 mod
->mux
->bih
->biBitCount
= 24;
298 mod
->mux
->bih
->biCompression
= mmioFOURCC('h', '2', '6', '4');
303 vf_info_t ve_info_x264
= {
306 "Bernhard Rosenkraenzer <bero@arklinux.org>",
307 "(C) 2004 LINUX4MEDIA GmbH; (C) 2004 Ark Linux",