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 encode_nals(uint8_t *buf
, int size
, x264_nal_t
*nals
, int nnal
){
66 for(i
= 0; i
< nnal
; i
++){
67 int s
= x264_nal_encode(p
, &size
, 1, nals
+ i
);
76 static int put_image(struct vf_instance_s
*vf
, mp_image_t
*mpi
, double pts
);
77 static int encode_frame(struct vf_instance_s
*vf
, x264_picture_t
*pic_in
);
79 void x264enc_set_param(const m_option_t
* opt
, char* arg
)
81 static int initted
= 0;
83 x264_param_default(¶m
);
84 x264_param_parse(¶m
, "psnr", "no");
85 x264_param_parse(¶m
, "ssim", "no");
99 arg
+= strcspn(arg
, ":");
105 value
= strchr( name
, '=' );
111 if(!strcmp(name
, "turbo")) {
112 turbo
= value
? atoi(value
) : 1;
116 ret
= x264_param_parse(¶m
, name
, value
);
117 if(ret
== X264_PARAM_BAD_NAME
)
118 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Option x264encopts: Unknown suboption %s\n", name
);
119 if(ret
== X264_PARAM_BAD_VALUE
)
120 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Option x264encopts: Bad argument %s=%s\n", name
, value
? value
: "(null)");
122 /* mark this option as done, so it's not reparsed if there's another -x264encopts */
128 if(param
.rc
.b_stat_write
&& !param
.rc
.b_stat_read
) {
129 /* Adjust or disable some flags to gain speed in the first pass */
132 param
.i_frame_reference
= ( param
.i_frame_reference
+ 1 ) >> 1;
133 param
.analyse
.i_subpel_refine
= FFMAX( FFMIN( 3, param
.analyse
.i_subpel_refine
- 1 ), 1 );
134 param
.analyse
.inter
&= ( ~X264_ANALYSE_PSUB8x8
);
135 param
.analyse
.inter
&= ( ~X264_ANALYSE_BSUB16x16
);
136 param
.analyse
.i_trellis
= 0;
140 param
.i_frame_reference
= 1;
141 param
.analyse
.i_subpel_refine
= 1;
142 param
.analyse
.i_me_method
= X264_ME_DIA
;
143 param
.analyse
.inter
= 0;
144 param
.analyse
.b_transform_8x8
= 0;
145 param
.analyse
.b_weighted_bipred
= 0;
146 param
.analyse
.i_trellis
= 0;
151 static int config(struct vf_instance_s
* vf
, int width
, int height
, int d_width
, int d_height
, unsigned int flags
, unsigned int outfmt
) {
152 h264_module_t
*mod
=(h264_module_t
*)vf
->priv
;
157 mod
->mux
->bih
->biWidth
= width
;
158 mod
->mux
->bih
->biHeight
= height
;
159 mod
->mux
->bih
->biSizeImage
= width
* height
* 3;
160 mod
->mux
->aspect
= (float)d_width
/d_height
;
162 // make sure param is initialized
163 x264enc_set_param(NULL
, "");
164 param
.i_width
= width
;
165 param
.i_height
= height
;
166 param
.i_fps_num
= mod
->mux
->h
.dwRate
;
167 param
.i_fps_den
= mod
->mux
->h
.dwScale
;
168 param
.vui
.i_sar_width
= d_width
*height
;
169 param
.vui
.i_sar_height
= d_height
*width
;
171 x264_param_parse(¶m
, "stats", passtmpfile
);
175 param
.i_csp
= X264_CSP_I420
;
178 param
.i_csp
= X264_CSP_YV12
;
181 mp_msg(MSGT_MENCODER
, MSGL_ERR
, "Wrong colorspace.\n");
185 mod
->x264
= x264_encoder_open(¶m
);
187 mp_msg(MSGT_MENCODER
, MSGL_ERR
, "x264_encoder_open failed.\n");
191 if(!param
.b_repeat_headers
){
194 int extradata_size
, nnal
, i
, s
= 0;
196 x264_encoder_headers(mod
->x264
, &nal
, &nnal
);
198 /* 5 bytes NAL header + worst case escaping */
199 for(i
= 0; i
< nnal
; i
++)
200 s
+= 5 + nal
[i
].i_payload
* 4 / 3;
202 extradata
= malloc(s
);
203 extradata_size
= encode_nals(extradata
, s
, nal
, nnal
);
205 mod
->mux
->bih
= realloc(mod
->mux
->bih
, sizeof(BITMAPINFOHEADER
) + extradata_size
);
206 memcpy(mod
->mux
->bih
+ 1, extradata
, extradata_size
);
207 mod
->mux
->bih
->biSize
= sizeof(BITMAPINFOHEADER
) + extradata_size
;
210 if (param
.i_bframe
> 1 && param
.b_bframe_pyramid
)
211 mod
->mux
->decoder_delay
= 2;
213 mod
->mux
->decoder_delay
= param
.i_bframe
? 1 : 0;
218 static int control(struct vf_instance_s
* vf
, int request
, void *data
)
220 h264_module_t
*mod
=(h264_module_t
*)vf
->priv
;
222 case VFCTRL_FLUSH_FRAMES
:
224 while(encode_frame(vf
, NULL
) > 0);
227 return CONTROL_UNKNOWN
;
231 static int query_format(struct vf_instance_s
* vf
, unsigned int fmt
)
235 return VFCAP_CSP_SUPPORTED
| VFCAP_CSP_SUPPORTED_BY_HW
;
243 /* These colorspaces are supported, but they'll just have
244 * to be converted to I420 internally */
245 return 0; /* VFCAP_CSP_SUPPORTED */
250 static int put_image(struct vf_instance_s
*vf
, mp_image_t
*mpi
, double pts
)
252 h264_module_t
*mod
=(h264_module_t
*)vf
->priv
;
255 memset(&mod
->pic
, 0, sizeof(x264_picture_t
));
256 mod
->pic
.img
.i_csp
=param
.i_csp
;
257 mod
->pic
.img
.i_plane
=3;
259 mod
->pic
.img
.plane
[i
] = mpi
->planes
[i
];
260 mod
->pic
.img
.i_stride
[i
] = mpi
->stride
[i
];
263 mod
->pic
.i_type
= X264_TYPE_AUTO
;
265 return encode_frame(vf
, &mod
->pic
) >= 0;
268 static int encode_frame(struct vf_instance_s
*vf
, x264_picture_t
*pic_in
)
270 h264_module_t
*mod
=(h264_module_t
*)vf
->priv
;
271 x264_picture_t pic_out
;
277 if(x264_encoder_encode(mod
->x264
, &nal
, &i_nal
, pic_in
, &pic_out
) < 0) {
278 mp_msg(MSGT_MENCODER
, MSGL_ERR
, "x264_encoder_encode failed\n");
282 for(i
=0; i
< i_nal
; i
++) {
283 int i_data
= mod
->mux
->buffer_size
- i_size
;
284 i_size
+= x264_nal_encode(mod
->mux
->buffer
+ i_size
, &i_data
, 1, &nal
[i
]);
287 int keyframe
= (pic_out
.i_type
== X264_TYPE_IDR
) ||
288 (pic_out
.i_type
== X264_TYPE_I
289 && param
.i_frame_reference
== 1
291 muxer_write_chunk(mod
->mux
, i_size
, keyframe
?0x10:0, MP_NOPTS_VALUE
, MP_NOPTS_VALUE
);
294 ++mod
->mux
->encoder_delay
;
299 static void uninit(struct vf_instance_s
*vf
)
301 h264_module_t
*mod
=(h264_module_t
*)vf
->priv
;
303 x264_encoder_close(mod
->x264
);
306 static int vf_open(vf_instance_t
*vf
, char *args
) {
310 vf
->default_caps
= VFCAP_CONSTANT
;
311 vf
->control
= control
;
312 vf
->query_format
= query_format
;
313 vf
->put_image
= put_image
;
315 vf
->priv
= malloc(sizeof(h264_module_t
));
317 mod
=(h264_module_t
*)vf
->priv
;
318 mod
->mux
= (muxer_stream_t
*)args
;
319 mod
->mux
->bih
= malloc(sizeof(BITMAPINFOHEADER
));
320 memset(mod
->mux
->bih
, 0, sizeof(BITMAPINFOHEADER
));
321 mod
->mux
->bih
->biSize
= sizeof(BITMAPINFOHEADER
);
322 mod
->mux
->bih
->biPlanes
= 1;
323 mod
->mux
->bih
->biBitCount
= 24;
324 mod
->mux
->bih
->biCompression
= mmioFOURCC('h', '2', '6', '4');
329 vf_info_t ve_info_x264
= {
332 "Bernhard Rosenkraenzer <bero@arklinux.org>",
333 "(C) 2004 LINUX4MEDIA GmbH; (C) 2004 Ark Linux",