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"
51 typedef struct h264_module_t
{
57 extern char* passtmpfile
;
59 static x264_param_t param
;
60 static int parse_error
= 0;
62 static int put_image(struct vf_instance
*vf
, mp_image_t
*mpi
, double pts
);
63 static int encode_frame(struct vf_instance
*vf
, x264_picture_t
*pic_in
);
65 void x264enc_set_param(const m_option_t
* opt
, char* arg
)
67 static int initted
= 0;
69 x264_param_default(¶m
);
70 x264_param_parse(¶m
, "psnr", "no");
71 x264_param_parse(¶m
, "ssim", "no");
85 arg
+= strcspn(arg
, ":");
91 value
= strchr( name
, '=' );
97 if(!strcmp(name
, "turbo")) {
98 turbo
= value
? atoi(value
) : 1;
102 ret
= x264_param_parse(¶m
, name
, value
);
103 if(ret
== X264_PARAM_BAD_NAME
)
104 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Option x264encopts: Unknown suboption %s\n", name
);
105 if(ret
== X264_PARAM_BAD_VALUE
)
106 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Option x264encopts: Bad argument %s=%s\n", name
, value
? value
: "(null)");
108 /* mark this option as done, so it's not reparsed if there's another -x264encopts */
114 if(param
.rc
.b_stat_write
&& !param
.rc
.b_stat_read
) {
115 /* Adjust or disable some flags to gain speed in the first pass */
118 param
.i_frame_reference
= ( param
.i_frame_reference
+ 1 ) >> 1;
119 param
.analyse
.i_subpel_refine
= FFMAX( FFMIN( 3, param
.analyse
.i_subpel_refine
- 1 ), 1 );
120 param
.analyse
.inter
&= ( ~X264_ANALYSE_PSUB8x8
);
121 param
.analyse
.inter
&= ( ~X264_ANALYSE_BSUB16x16
);
122 param
.analyse
.i_trellis
= 0;
126 param
.i_frame_reference
= 1;
127 param
.analyse
.i_subpel_refine
= 1;
128 param
.analyse
.i_me_method
= X264_ME_DIA
;
129 param
.analyse
.inter
= 0;
130 param
.analyse
.b_transform_8x8
= 0;
131 param
.analyse
.b_weighted_bipred
= 0;
132 param
.analyse
.i_trellis
= 0;
137 static int config(struct vf_instance
* vf
, int width
, int height
, int d_width
, int d_height
, unsigned int flags
, unsigned int outfmt
) {
138 h264_module_t
*mod
=(h264_module_t
*)vf
->priv
;
143 mod
->mux
->bih
->biWidth
= width
;
144 mod
->mux
->bih
->biHeight
= height
;
145 mod
->mux
->bih
->biSizeImage
= width
* height
* 3;
146 mod
->mux
->aspect
= (float)d_width
/d_height
;
148 // make sure param is initialized
149 x264enc_set_param(NULL
, "");
150 param
.i_width
= width
;
151 param
.i_height
= height
;
152 param
.i_fps_num
= mod
->mux
->h
.dwRate
;
153 param
.i_fps_den
= mod
->mux
->h
.dwScale
;
154 param
.vui
.i_sar_width
= d_width
*height
;
155 param
.vui
.i_sar_height
= d_height
*width
;
157 x264_param_parse(¶m
, "stats", passtmpfile
);
161 param
.i_csp
= X264_CSP_I420
;
164 param
.i_csp
= X264_CSP_YV12
;
167 mp_msg(MSGT_MENCODER
, MSGL_ERR
, "Wrong colorspace.\n");
171 mod
->x264
= x264_encoder_open(¶m
);
173 mp_msg(MSGT_MENCODER
, MSGL_ERR
, "x264_encoder_open failed.\n");
177 if(!param
.b_repeat_headers
){
179 int extradata_size
, nnal
;
181 extradata_size
= x264_encoder_headers(mod
->x264
, &nal
, &nnal
);
183 mod
->mux
->bih
= realloc(mod
->mux
->bih
, sizeof(BITMAPINFOHEADER
) + extradata_size
);
184 memcpy(mod
->mux
->bih
+ 1, nal
->p_payload
, extradata_size
);
185 mod
->mux
->bih
->biSize
= sizeof(BITMAPINFOHEADER
) + extradata_size
;
188 if (param
.i_bframe
> 1 && param
.i_bframe_pyramid
)
189 mod
->mux
->decoder_delay
= 2;
191 mod
->mux
->decoder_delay
= param
.i_bframe
? 1 : 0;
196 static int control(struct vf_instance
* vf
, int request
, void *data
)
198 h264_module_t
*mod
=(h264_module_t
*)vf
->priv
;
200 case VFCTRL_FLUSH_FRAMES
:
201 while (x264_encoder_delayed_frames(mod
->x264
) > 0)
202 encode_frame(vf
, NULL
);
205 return CONTROL_UNKNOWN
;
209 static int query_format(struct vf_instance
* vf
, unsigned int fmt
)
213 return VFCAP_CSP_SUPPORTED
| VFCAP_CSP_SUPPORTED_BY_HW
;
221 /* These colorspaces are supported, but they'll just have
222 * to be converted to I420 internally */
223 return 0; /* VFCAP_CSP_SUPPORTED */
228 static int put_image(struct vf_instance
*vf
, mp_image_t
*mpi
, double pts
)
230 h264_module_t
*mod
=(h264_module_t
*)vf
->priv
;
233 memset(&mod
->pic
, 0, sizeof(x264_picture_t
));
234 mod
->pic
.img
.i_csp
=param
.i_csp
;
235 mod
->pic
.img
.i_plane
=3;
237 mod
->pic
.img
.plane
[i
] = mpi
->planes
[i
];
238 mod
->pic
.img
.i_stride
[i
] = mpi
->stride
[i
];
241 mod
->pic
.i_type
= X264_TYPE_AUTO
;
243 return encode_frame(vf
, &mod
->pic
) >= 0;
246 static int encode_frame(struct vf_instance
*vf
, x264_picture_t
*pic_in
)
248 h264_module_t
*mod
=(h264_module_t
*)vf
->priv
;
249 x264_picture_t pic_out
;
254 i_size
= x264_encoder_encode(mod
->x264
, &nal
, &i_nal
, pic_in
, &pic_out
);
257 mp_msg(MSGT_MENCODER
, MSGL_ERR
, "x264_encoder_encode failed\n");
261 int keyframe
= (pic_out
.i_type
== X264_TYPE_IDR
) ||
262 (pic_out
.i_type
== X264_TYPE_I
263 && param
.i_frame_reference
== 1
265 memcpy(mod
->mux
->buffer
, nal
->p_payload
, i_size
);
266 muxer_write_chunk(mod
->mux
, i_size
, keyframe
?0x10:0, MP_NOPTS_VALUE
, MP_NOPTS_VALUE
);
269 ++mod
->mux
->encoder_delay
;
274 static void uninit(struct vf_instance
*vf
)
276 h264_module_t
*mod
=(h264_module_t
*)vf
->priv
;
278 x264_encoder_close(mod
->x264
);
281 static int vf_open(vf_instance_t
*vf
, char *args
) {
285 vf
->default_caps
= VFCAP_CONSTANT
;
286 vf
->control
= control
;
287 vf
->query_format
= query_format
;
288 vf
->put_image
= put_image
;
290 vf
->priv
= malloc(sizeof(h264_module_t
));
292 mod
=(h264_module_t
*)vf
->priv
;
293 mod
->mux
= (muxer_stream_t
*)args
;
294 mod
->mux
->bih
= malloc(sizeof(BITMAPINFOHEADER
));
295 memset(mod
->mux
->bih
, 0, sizeof(BITMAPINFOHEADER
));
296 mod
->mux
->bih
->biSize
= sizeof(BITMAPINFOHEADER
);
297 mod
->mux
->bih
->biPlanes
= 1;
298 mod
->mux
->bih
->biBitCount
= 24;
299 mod
->mux
->bih
->biCompression
= mmioFOURCC('h', '2', '6', '4');
304 vf_info_t ve_info_x264
= {
307 "Bernhard Rosenkraenzer <bero@arklinux.org>",
308 "(C) 2004 LINUX4MEDIA GmbH; (C) 2004 Ark Linux",