[MPlayer-dev-eng] [PATCH] H.264 encoding in mencoder
Jeff Clagg
snacky at ikaruga.co.uk
Fri Aug 27 17:07:04 CEST 2004
Here comes the latest patch. It is significantly better.
Last time, I submitted a patch that was several revisions behind the
latest x264. This time, thanks to Loren Merritt, it is actually ahead of
the official version. This is because there is a patch allowing 2-pass
encoding, again thanks to Loren Merritt.
Get the latest x264 with:
svn co svn://svn.videolan.org/x264/trunk x264
Obtain a very slightly modified version (fixed Makefiles) of the x264
2-pass patch at:
http://ikaruga.co.uk/~snacky/x264_2pass.patch
I highly recommend giving this thing a try. Particularly with low-noise
animation source material, the results are just about unbeatable
with any other codec. Now all we need is support for muxing to a more
appropriate container format, and mplayer will be the software of choice
for transcoding to H.264 ;-)
-------------- next part --------------
diff -ruN main.orig/DOCS/man/en/mplayer.1 main/DOCS/man/en/mplayer.1
--- main.orig/DOCS/man/en/mplayer.1 2004-08-26 22:12:11.000000000 -0400
+++ main/DOCS/man/en/mplayer.1 2004-08-27 10:13:51.000000000 -0400
@@ -4308,7 +4308,7 @@
.RE
.br
.PP
-Where <codec> may be: lavc, xvidenc, divx4, lame
+Where <codec> may be: lavc, xvidenc, divx4, lame, x264
.
.
.SS divx4 (\-divx4opts)
@@ -5725,6 +5725,142 @@
and store the per frame psnr in a file with a name like 'psnr_hhmmss.log' in
the current directory.
Returned values are in dB (decibel), the higher the better.
+SS x264enc (\-x264encopts)
+.TP
+.B bitrate=<value>
+Sets the bitrate to be used in kbits/\:second (default: off).
+This is required if you want a CBR (constant bitrate) encode.
+.TP
+.B iframe=<value>
+Frequency of I frames (default: 60)
+.TP
+.B frameref=<value>
+Number of previous frames used as predictors in a P-frame (default: 1)
+.br
+.I NOTE:
+The current version of x264 (r38) hasn't yet implemented this feature.
+.TP
+.B idrframe=<value>
+Each <value> I-Frames are IDR-Frames.
+In H.264, I-Frames do not necessarily bound a closed GOP because it is
+allowable for a P-frame to be predicted from more frames than just the one
+frame before it (see the frameref option).
+Therefore, I-frames are not necessarily seekable. IDR-Frames restrict
+subsequent P-frames from referring to any frame prior to the IDR-Frame
+(default: 2)
+.TP
+.B bframe=<value>
+Number of B-Frames between I- and P-Frames (default: 0)
+.TP
+.B deblock=<0|1>
+Use deblocking filter (default: on)
+.TP
+.B deblockalpha=<-6-6>
+AlphaC0 parameter of deblocking filter.
+This adjusts thresholds for the H.264 deblocking filter.
+First, this parameter adjusts the maximum amount of change that the filter is
+allowed to cause on any one pixel.
+Secondly, this parameter affects the threshold for difference across the
+edge being filtered.
+A positive value reduces blocking artifacts more, but will also smear details
+(default: 0)
+.TP
+.B deblockbeta=<-6-6>
+Beta parameter of deblocking filter.
+Affects the maximum allowed gradient within two adjacent blocks (default: 0)
+.TP
+.B cabac
+Use CABAC (Context-Adaptive Binary Arithmetic Coding) (default: off)
+.TP
+.B cabacidc=<value>
+Initial value of CABAC IDC.
+The encoder must choose a context for each block it encodes, but for the
+first block in a frame, there are no prior blocks to predict the context.
+Adjusting this may affect bitrate by a fraction of a percent, but it doesn't
+directly affect distortion.
+.RSs
+-1: Let the encoder decide which context (default) (it usually chooses 0)
+.br
+0: low complexity
+.br
+1: medium complexity
+.br
+2: high complexity
+.REss
+.TP
+.B qp_constant=<2-51>
+This selects the quantizer to use.
+Lower values result in better fidelity, but higher bitrates.
+Note that quantization in H.264 works differently from mpeg[124].
+H.264's QP is on a logarithmic scale. As an example, the bitrate difference
+between QP=20 and QP=40 is about a factor of 10.
+Useful quantizers in H.264 tend to be very large compared to mpeg[124].
+20-40 is a useful range (default: 26)
+.br
+.I NOTE:
+This option takes effect even if you specify a cbr encode.
+In such a case, the first frame encoded will use the quantization factor you
+specified, but in later frames, the ratecontrol decides what quants to use.
+.TP
+.B qp_min=<2-51>
+Minimum quantizer. CBR only. 20-40 seems to be a useful range (default: 2)
+.TP
+.B qp_max=<2-51>
+Maximum quantizer. CBR only.
+.TP
+.B qp_step=<value>
+Maximum Value by which the quantizer may be incremented/decremented between
+frames.
+.TP
+.B rc_buffer_size=<value>
+Size of the ratecontrol buffer. (default: 1 second's worth at the bitrate you
+specified)
+.TP
+.B rc_init_buffer=<value>
+Set the initial size of ratecontrol buffer (default: 1/4 of rc_buffer_size)
+.B rc_sens=<0-100>
+Ratecontrol sensitivity (default: 100)
+.TP
+.B ip_factor=<value>
+Quantizer factor between I amd P frames (default: 2.0)
+.TP
+.B pb_factor=<value>
+Quantizer factor between P and B frames (default: 2.0)
+.TP
+.B pass=<1|2>
+For 2-pass mode.
+The first pass saves statistics to x2642pass.log.
+.TP
+.B qcompress=<0-1>
+Quantizer compression. This affects the ratecontrol: a lower value makes the
+bitrate more constant, while a higher value makes the quantization parameter
+more constant (default: 0.6)
+.TP
+.B qblur=<0-1>
+Temporal blur of the quantization parameter. Lower values allow the quantizer
+value to jump around more; higher values force it to vary more smoothly
+(default: 0.5)
+.TP
+.B fullinter
+Use all available interframe analyse methods (i4x4, psub8x8, psub16x16)
+(default: 4x4, psub16x16)
+.TP
+.B log=<-1-3>
+Adjust the amount of logging info printed to the screen.
+.RSs
+-1: none
+.br
+ 0: errors (for debugging x264)
+.br
+ 1: warnings
+.br
+ 2: PSNR and other analysis stats when the encode finishes (default)
+.br
+ 3: PSNR, qp, frametype, size, and other stats for every frame
+.REss
+.TP
+.B psnr
+Print signal-to-noise ratio statistics.
.
.
.\" --------------------------------------------------------------------------
diff -ruN main.orig/Makefile main/Makefile
--- main.orig/Makefile 2004-08-22 20:25:19.000000000 -0400
+++ main/Makefile 2004-08-26 11:27:46.000000000 -0400
@@ -32,7 +32,7 @@
VO_LIBS = $(AA_LIB) $(X_LIB) $(SDL_LIB) $(GGI_LIB) $(MP1E_LIB) $(MLIB_LIB) $(SVGA_LIB) $(DIRECTFB_LIB) $(CACA_LIB)
AO_LIBS = $(ARTS_LIB) $(ESD_LIB) $(JACK_LIB) $(NAS_LIB) $(SGIAUDIO_LIB)
-CODEC_LIBS = $(AV_LIB) $(FAME_LIB) $(MAD_LIB) $(VORBIS_LIB) $(THEORA_LIB) $(FAAD_LIB) $(LIBLZO_LIB) $(DECORE_LIB) $(XVID_LIB) $(DTS_LIB) $(PNG_LIB) $(Z_LIB) $(JPEG_LIB) $(ALSA_LIB) $(XMMS_LIB)
+CODEC_LIBS = $(AV_LIB) $(FAME_LIB) $(MAD_LIB) $(VORBIS_LIB) $(THEORA_LIB) $(FAAD_LIB) $(LIBLZO_LIB) $(DECORE_LIB) $(XVID_LIB) $(DTS_LIB) $(PNG_LIB) $(Z_LIB) $(JPEG_LIB) $(ALSA_LIB) $(XMMS_LIB) $(X264_LIB)
COMMON_LIBS = libmpcodecs/libmpcodecs.a mp3lib/libMP3.a liba52/liba52.a libmpeg2/libmpeg2.a $(W32_LIB) $(DS_LIB) libaf/libaf.a libmpdemux/libmpdemux.a input/libinput.a postproc/libswscale.a osdep/libosdep.a $(DVDREAD_LIB) $(CODEC_LIBS) $(FREETYPE_LIB) $(TERMCAP_LIB) $(CDPARANOIA_LIB) $(MPLAYER_NETWORK_LIB) $(WIN32_LIB) $(GIF_LIB) $(MACOSX_FRAMEWORKS) $(SMBSUPPORT_LIB) $(FRIBIDI_LIB) $(FONTCONFIG_LIB) $(ENCA_LIB)
CFLAGS = $(OPTFLAGS) -Ilibmpdemux -Iloader -Ilibvo $(FREETYPE_INC) $(EXTRA_INC) $(CDPARANOIA_INC) $(SDL_INC) $(X11_INC) $(FRIBIDI_INC) $(DVB_INC) $(XVID_INC) $(FONTCONFIG_INC) $(CACA_INC) # -Wall
diff -ruN main.orig/cfg-mencoder.h main/cfg-mencoder.h
--- main.orig/cfg-mencoder.h 2004-05-19 00:33:00.000000000 -0400
+++ main/cfg-mencoder.h 2004-08-26 11:27:46.000000000 -0400
@@ -63,6 +63,10 @@
extern m_option_t xvidencopts_conf[];
#endif
+#if defined(HAVE_X264)
+extern m_option_t x264encopts_conf[];
+#endif
+
extern m_option_t nuvopts_conf[];
m_option_t ovc_conf[]={
@@ -78,6 +82,7 @@
{"xvid", &out_video_codec, CONF_TYPE_FLAG, 0, 0, VCODEC_XVID, NULL},
{"qtvideo", &out_video_codec, CONF_TYPE_FLAG, 0, 0, VCODEC_QTVIDEO, NULL},
{"nuv", &out_video_codec, CONF_TYPE_FLAG, 0, 0, VCODEC_NUV, NULL},
+ {"x264", &out_video_codec, CONF_TYPE_FLAG, 0, 0, VCODEC_X264, NULL},
{"help", "\nAvailable codecs:\n"
" copy - frame copy, without re-encoding. Doesn't work with filters.\n"
" frameno - special audio-only file for 3-pass encoding, see DOCS.\n"
@@ -103,6 +108,9 @@
#if defined(HAVE_XVID3) || defined(HAVE_XVID4)
" xvid - XviD encoding\n"
#endif
+#ifdef HAVE_X264
+ " x264 - H.264 encoding\n"
+#endif
"\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
{NULL, NULL, 0, 0, 0, 0, NULL}
};
@@ -239,6 +247,9 @@
#if defined(HAVE_XVID3) || defined(HAVE_XVID4)
{"xvidencopts", xvidencopts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
#endif
+#if defined(HAVE_X264)
+ {"x264encopts", x264encopts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
+#endif
{"nuvopts", nuvopts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
diff -ruN main.orig/configure main/configure
--- main.orig/configure 2004-08-26 05:24:03.000000000 -0400
+++ main/configure 2004-08-27 10:24:51.000000000 -0400
@@ -198,6 +198,7 @@
--disable-xanim disable XAnim DLL support [autodetect]
--disable-real disable RealPlayer DLL support [autodetect]
--disable-xvid disable XviD codec [autodetect]
+ --disable-x264 disable H.264 encoder [autodetect]
--disable-divx4linux disable DivX4linux/Divx5linux codec [autodetect]
--enable-opendivx enable _old_ OpenDivx codec [disable]
--disable-libavcodec disable libavcodec [autodetect]
@@ -320,6 +321,8 @@
--with-reallibdir=DIR RealPlayer DLL files in DIR
--with-xvidlibdir=DIR libxvidcore (XviD) in DIR (*)
--with-xvidincdir=DIR XviD header in DIR (*)
+ --with-x264libdir=DIR libx264 in DIR
+ --with-x264incdir=DIR x264 header in DIR
--with-dtslibdir=DIR libdts library in DIR (*)
--with-dtsincdir=DIR libdts header in DIR (*)
--with-livelibdir=DIR LIVE.COM Streaming Media libraries in DIR
@@ -1298,6 +1301,7 @@
_vidix=auto
_joystick=no
_xvid=auto
+_x264=auto
_divx4linux=auto
_opendivx=no
_lirc=auto
@@ -1502,6 +1506,8 @@
--disable-joystick) _joystick=no ;;
--enable-xvid) _xvid=yes ;;
--disable-xvid) _xvid=no ;;
+ --enable-x264) _x264=yes ;;
+ --disable-x264) _x264=no ;;
--enable-divx4linux) _divx4linux=yes ;;
--disable-divx4linux) _divx4linux=no ;;
--enable-opendivx) _opendivx=yes ;;
@@ -1708,6 +1714,12 @@
--with-dtsincdir=*)
_inc_libdts=-I`echo $ac_option | cut -d '=' -f 2 | sed 's,:, -I,g'`
;;
+ --with-x264libdir=*)
+ _ld_x264=-L`echo $ac_option | cut -d '=' -f 2 | sed 's,:, -L,g'`
+ ;;
+ --with-x264incdir=*)
+ _inc_x264=-I`echo $ac_option | cut -d '=' -f 2 |sed 's,:, -I,g'`
+ ;;
--with-sdl-config=*)
_sdlconfig=`echo $ac_option | cut -d '=' -f 2`
;;
@@ -5474,6 +5486,25 @@
echores "$_xvidcompat"
fi
+echocheck "x264"
+cat > $TMPC << EOF
+#include <stdint.h>
+#include <stdarg.h>
+#include <x264.h>
+int main(void) { x264_encoder_open((void*)0); return 0; }
+EOF
+_ld_x264="$_ld_x264 -lx264 -lm"
+if test "$_x264" != no && cc_check $_inc_x264 $_ld_x264 ; then
+ _x264=yes
+ _def_x264='#define HAVE_X264 1'
+ _codecmodules="x264 $_codecmodules"
+else
+ _x264=no
+ _ld_x264=''
+ _def_x264='#undef HAVE_X264'
+ _nocodecmodules="x264 $_nocodecmodules"
+fi
+echores "$_x264"
echocheck "DivX4linux/DivX5linux/OpenDivX decore"
# DivX5: DEC_OPT_MEMORY_REQS - DivX4: DEC_OPT_FRAME_311
@@ -6268,6 +6299,9 @@
XVID = $_xvid
XVID_INC = $_inc_xvid
XVID_LIB = $_ld_xvid
+X264 = $_x264
+X264_INC = $_inc_x264
+X264_LIB = $_ld_x264
CONFIG_DTS = $_libdts
DTS_INC = $_inc_libdts
DTS_LIB = $_ld_libdts
@@ -6410,6 +6444,9 @@
$_def_decore_xvid
$_def_encore_xvid
+/* Define if you are using the X.264 library */
+$_def_x264
+
/* Define to include support for libdv-0.9.5 */
$_def_libdv
diff -ruN main.orig/libmpcodecs/Makefile main/libmpcodecs/Makefile
--- main.orig/libmpcodecs/Makefile 2004-07-15 16:36:04.000000000 -0400
+++ main/libmpcodecs/Makefile 2004-08-26 11:27:46.000000000 -0400
@@ -19,7 +19,7 @@
VFILTER_SRCS += vf_pp.c
endif
-ENCODER_SRCS=ve.c ve_divx4.c ve_lavc.c ve_vfw.c ve_raw.c ve_libdv.c ve_xvid.c ve_xvid4.c ve_qtvideo.c ve_nuv.c
+ENCODER_SRCS=ve.c ve_divx4.c ve_lavc.c ve_vfw.c ve_raw.c ve_libdv.c ve_xvid.c ve_xvid4.c ve_qtvideo.c ve_nuv.c ve_x264.c
NATIVE_SRCS=native/RTjpegN.c native/minilzo.c native/nuppelvideo.c native/xa_gsm.c native/decode144.c native/decode288.c
diff -ruN main.orig/libmpcodecs/ve.c main/libmpcodecs/ve.c
--- main.orig/libmpcodecs/ve.c 2004-02-17 07:43:07.000000000 -0500
+++ main/libmpcodecs/ve.c 2004-08-26 11:27:46.000000000 -0400
@@ -17,6 +17,7 @@
extern vf_info_t ve_info_xvid;
extern vf_info_t ve_info_qtvideo;
extern vf_info_t ve_info_nuv;
+extern vf_info_t ve_info_x264;
static vf_info_t* encoder_list[]={
#ifdef HAVE_DIVX4ENCORE
@@ -37,6 +38,9 @@
&ve_info_xvid,
#endif
&ve_info_nuv,
+#ifdef HAVE_X264
+ &ve_info_x264,
+#endif
NULL
};
diff -ruN main.orig/libmpcodecs/ve_x264.c main/libmpcodecs/ve_x264.c
--- main.orig/libmpcodecs/ve_x264.c 1969-12-31 19:00:00.000000000 -0500
+++ main/libmpcodecs/ve_x264.c 2004-08-27 10:03:21.000000000 -0400
@@ -0,0 +1,322 @@
+/*****************************************************************************
+ *
+ * - H.264 encoder for mencoder using x264 -
+ *
+ * Copyright (C) 2004 LINUX4MEDIA GmbH
+ * Copyright (C) 2004 Ark Linux
+ *
+ * Written by Bernhard Rosenkraenzer <bero at arklinux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation, or if, and only if,
+ * version 2 is ruled invalid in a court of law, any later version
+ * of the GNU General Public License published by the Free Software
+ * Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include "../config.h"
+#include "../mp_msg.h"
+
+#ifdef HAVE_X264
+
+#include "m_option.h"
+#include "codec-cfg.h"
+#include "stream.h"
+#include "demuxer.h"
+#include "stheader.h"
+
+#include "muxer.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#include <x264.h>
+
+typedef struct _h264_module_t {
+ muxer_stream_t *mux;
+ x264_param_t param;
+ x264_t * x264;
+ x264_picture_t pic;
+} h264_module_t;
+
+extern char* passtmpfile = "x2642pass.log";
+
+static int bitrate = -1;
+static int qp_constant = 26;
+static int frame_ref = 1;
+static int iframe = 60;
+static int idrframe = 2;
+static int bframe = 0;
+static int deblock = 1;
+static int deblockalpha = 0;
+static int deblockbeta = 0;
+static int cabac = 0;
+static int cabacidc = -1;
+static int fullinter = 0;
+static float ip_factor = 2.0;
+static float pb_factor = 2.0;
+static int rc_buffer_size = -1;
+static int rc_init_buffer = -1;
+static int rc_sens = 4;
+static int qp_min = 10;
+static int qp_max = 51;
+static int qp_step = 1;
+static int pass = 0;
+static float qcomp = 0.6;
+static float qblur = 0.5;
+static char *rc_eq = "(tex^qComp)*(avgTex^(1-qComp))";
+static int psnr = 0;
+static int log_level = 2;
+
+m_option_t x264encopts_conf[] = {
+ {"bitrate", &bitrate, CONF_TYPE_INT, CONF_RANGE, 0, 24000000, NULL},
+ {"qp_constant", &qp_constant, CONF_TYPE_INT, CONF_RANGE, 1, 51, NULL},
+ {"frameref", &frame_ref, CONF_TYPE_INT, CONF_RANGE, 1, 100, NULL},
+ {"iframe", &iframe, CONF_TYPE_INT, CONF_RANGE, 1, 24000000, NULL},
+ {"idrframe", &idrframe, CONF_TYPE_INT, CONF_RANGE, 1, 24000000, NULL},
+ {"bframe", &bframe, CONF_TYPE_INT, CONF_RANGE, 0, 10, NULL},
+ {"deblock", &deblock, CONF_TYPE_INT, CONF_RANGE, 0, 1, NULL},
+ {"deblockalpha", &deblockalpha, CONF_TYPE_INT, CONF_RANGE, -6, 6, NULL},
+ {"deblockbeta", &deblockbeta, CONF_TYPE_INT, CONF_RANGE, -6, 6, NULL},
+ {"cabac", &cabac, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+ {"cabacidc", &cabacidc, CONF_TYPE_INT, CONF_RANGE, -1, 2, NULL},
+ {"fullinter", &fullinter, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+ {"ip_factor", &ip_factor, CONF_TYPE_FLOAT, CONF_RANGE, -10.0, 10.0, NULL},
+ {"pb_factor", &pb_factor, CONF_TYPE_FLOAT, CONF_RANGE, -10.0, 10.0, NULL},
+ {"rc_buffer_size", &rc_buffer_size, CONF_TYPE_INT, CONF_RANGE, 0, 24000000, NULL},
+ {"rc_init_buffer", &rc_init_buffer, CONF_TYPE_INT, CONF_RANGE, 0, 24000000, NULL},
+ {"rc_sens", &rc_sens, CONF_TYPE_INT, CONF_RANGE, 0, 100, NULL},
+ {"qp_min", &qp_min, CONF_TYPE_INT, CONF_RANGE, 1, 51, NULL},
+ {"qp_max", &qp_max, CONF_TYPE_INT, CONF_RANGE, 1, 51, NULL},
+ {"qp_step", &qp_step, CONF_TYPE_INT, CONF_RANGE, 0, 50, NULL},
+ {"pass", &pass, CONF_TYPE_INT, CONF_RANGE, 1, 3, NULL},
+ {"rc_eq", &rc_eq, CONF_TYPE_STRING, 0, 0, 0, NULL},
+ {"qcomp", &qcomp, CONF_TYPE_FLOAT, CONF_RANGE, 0, 1, NULL},
+ {"qblur", &qblur, CONF_TYPE_FLOAT, CONF_RANGE, 0, 99, NULL},
+ {"psnr", &psnr, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+ {"log", &log_level, CONF_TYPE_INT, CONF_RANGE, -1, 3, NULL},
+ {NULL, NULL, 0, 0, 0, 0, NULL}
+};
+
+
+static int config(struct vf_instance_s* vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt) {
+ h264_module_t *mod=(h264_module_t*)vf->priv;
+ mod->mux->bih->biWidth = width;
+ mod->mux->bih->biHeight = height;
+ mod->mux->aspect = (float)d_width/d_height;
+
+ x264_param_default(&mod->param);
+ mod->param.i_frame_reference = frame_ref;
+ mod->param.i_idrframe = idrframe;
+ mod->param.i_iframe = iframe;
+ mod->param.i_bframe = bframe;
+ mod->param.b_deblocking_filter = deblock;
+ mod->param.i_deblocking_filter_alphac0 = deblockalpha;
+ mod->param.i_deblocking_filter_beta = deblockbeta;
+ mod->param.b_cabac = cabac;
+ mod->param.i_cabac_init_idc = cabacidc;
+ mod->param.i_qp_constant = qp_constant;
+ if(qp_min > qp_constant)
+ qp_min = qp_constant;
+ if(qp_max < qp_constant)
+ qp_max = qp_constant;
+ mod->param.i_qp_min = qp_min;
+ mod->param.i_qp_max = qp_max;
+ mod->param.i_qp_step = qp_step;
+
+ mod->param.i_pass = pass;
+ mod->param.s_rc_eq = rc_eq;
+ mod->param.f_qcompress = qcomp;
+ mod->param.f_qblur = qblur;
+ mod->param.s_2pass_file_out = passtmpfile;
+ mod->param.s_2pass_file_in = passtmpfile;
+ if((pass & 2) && bitrate <= 0)
+ {
+ mp_msg(MSGT_MENCODER, MSGL_ERR,
+ "2 pass encoding enabled, but no bitrate specified.\n");
+ return 0;
+ }
+
+ if(bitrate > 0) {
+ if(rc_buffer_size <= 0)
+ rc_buffer_size = bitrate;
+ if(rc_init_buffer < 0)
+ rc_init_buffer = rc_buffer_size/4;
+ mod->param.b_cbr = 1;
+ mod->param.i_bitrate = bitrate;
+ mod->param.i_rc_buffer_size = rc_buffer_size;
+ mod->param.i_rc_init_buffer = rc_init_buffer;
+ mod->param.i_rc_sens = rc_sens;
+ }
+ if(fullinter)
+ mod->param.analyse.inter = X264_ANALYSE_I4x4 | X264_ANALYSE_PSUB16x16 | X264_ANALYSE_PSUB8x8;
+ mod->param.f_ip_factor = ip_factor;
+ mod->param.f_pb_factor = pb_factor;
+
+ mod->param.i_width = width;
+ mod->param.i_height = height;
+ mod->param.i_fps_num = mod->mux->h.dwRate;
+ mod->param.i_fps_den = mod->mux->h.dwScale;
+ mod->param.analyse.b_psnr = psnr;
+ mod->param.i_log_level = log_level;
+
+ switch(outfmt) {
+ case IMGFMT_I420:
+ mod->param.i_csp = X264_CSP_I420;
+ mod->mux->bih->biSizeImage = width * height * 3;
+ break;
+ case IMGFMT_YV12:
+ mod->param.i_csp = X264_CSP_YV12;
+ mod->mux->bih->biSizeImage = width * height * 3;
+ break;
+ case IMGFMT_422P:
+ mod->param.i_csp = X264_CSP_I422;
+ mod->mux->bih->biSizeImage = width * height * 3;
+ break;
+ case IMGFMT_444P:
+ mod->param.i_csp = X264_CSP_I444;
+ mod->mux->bih->biSizeImage = width * height * 3;
+ break;
+ case IMGFMT_YVYU:
+ mod->param.i_csp = X264_CSP_YUYV;
+ mod->mux->bih->biSizeImage = width * height * 3;
+ break;
+ case IMGFMT_RGB:
+ mod->param.i_csp = X264_CSP_RGB;
+ mod->mux->bih->biSizeImage = width * height * 3;
+ break;
+ case IMGFMT_BGR:
+ mod->param.i_csp = X264_CSP_BGR;
+ mod->mux->bih->biSizeImage = width * height * 3;
+ break;
+ case IMGFMT_BGR32:
+ mod->param.i_csp = X264_CSP_BGRA;
+ mod->mux->bih->biSizeImage = width * height * 4;
+ break;
+ default:
+ mp_msg(MSGT_MENCODER, MSGL_ERR, "Wrong colorspace.\n");
+ return 0;
+ }
+
+ mod->x264 = x264_encoder_open(&mod->param);
+ if(!mod->x264) {
+ mp_msg(MSGT_MENCODER, MSGL_ERR, "x264_encoder_open failed.\n");
+ return 0;
+ }
+
+ x264_picture_alloc(&mod->pic, mod->param.i_csp, mod->param.i_width, mod->param.i_height);
+ return 1;
+}
+
+static int control(struct vf_instance_s* vf, int request, void *data)
+{
+ return CONTROL_UNKNOWN;
+}
+
+static int query_format(struct vf_instance_s* vf, unsigned int fmt)
+{
+ switch(fmt) {
+ case IMGFMT_I420:
+ return (VFCAP_CSP_SUPPORTED|VFCAP_CSP_SUPPORTED_BY_HW);
+ case IMGFMT_YV12:
+ case IMGFMT_422P:
+ case IMGFMT_444P:
+ case IMGFMT_YVYU:
+ case IMGFMT_RGB:
+ case IMGFMT_BGR:
+ case IMGFMT_BGR32:
+ /* 2004/08/05: There seems to be some, but not complete,
+ support for these colorspaces in X264. Better to stay
+ on the safe side for now. */
+ return 0; /* VFCAP_CSP_SUPPORTED */
+ }
+ return 0;
+}
+
+static int put_image(struct vf_instance_s *vf, mp_image_t *mpi)
+{
+ h264_module_t *mod=(h264_module_t*)vf->priv;
+ int i_nal;
+ x264_nal_t *nal;
+ int i;
+
+ int csp=mod->pic.img.i_csp;
+ memset(&mod->pic, 0, sizeof(x264_picture_t));
+ mod->pic.img.i_csp=csp;
+ mod->pic.img.i_plane=3;
+ for(i=0; i<4; i++) {
+ mod->pic.img.plane[i] = mpi->planes[i];
+ mod->pic.img.i_stride[i] = mpi->stride[i];
+ }
+
+ mod->pic.i_type = X264_TYPE_AUTO;
+ if(x264_encoder_encode(mod->x264, &nal, &i_nal, &mod->pic) < 0) {
+ mp_msg(MSGT_MENCODER, MSGL_ERR, "x264_encoder_encode failed\n");
+ return 0;
+ }
+
+ int i_size = 0;
+ for(i=0; i < i_nal; i++) {
+ int i_data = mod->mux->buffer_size - i_size;
+ i_size += x264_nal_encode(mod->mux->buffer + i_size, &i_data, 1, &nal[i]);
+ }
+ if(i_size>0) {
+ muxer_write_chunk(mod->mux, i_size, (mod->pic.i_type == X264_TYPE_I)?0x10:0);
+ }
+ return 1;
+}
+
+static void uninit(struct vf_instance_s *vf)
+{
+ // FIXME: flush delayed frames
+ h264_module_t *mod=(h264_module_t*)vf->priv;
+ x264_encoder_close(mod->x264);
+ //x264_picture_clean(&mod->pic);
+}
+
+static int vf_open(vf_instance_t *vf, char *args) {
+ vf->config = config;
+ vf->control = control;
+ vf->query_format = query_format;
+ vf->put_image = put_image;
+ vf->uninit = uninit;
+ vf->priv = malloc(sizeof(h264_module_t));
+
+ h264_module_t *mod=(h264_module_t*)vf->priv;
+ mod->mux = (muxer_stream_t*)args;
+ mod->mux->bih = malloc(sizeof(BITMAPINFOHEADER));
+ memset(mod->mux->bih, 0, sizeof(BITMAPINFOHEADER));
+ mod->mux->bih->biSize = sizeof(BITMAPINFOHEADER);
+ mod->mux->bih->biPlanes = 1;
+ mod->mux->bih->biBitCount = 24;
+ mod->mux->bih->biCompression = mmioFOURCC('h', '2', '6', '4');
+
+ return 1;
+}
+
+vf_info_t ve_info_x264 = {
+ "H.264 encoder",
+ "x264",
+ "Bernhard Rosenkraenzer <bero at arklinux.org>",
+ "(C) 2004 LINUX4MEDIA GmbH; (C) 2004 Ark Linux",
+ vf_open
+};
+#endif
diff -ruN main.orig/mencoder.c main/mencoder.c
--- main.orig/mencoder.c 2004-08-24 15:36:16.000000000 -0400
+++ main/mencoder.c 2004-08-26 11:27:46.000000000 -0400
@@ -9,6 +9,7 @@
#define VCODEC_QTVIDEO 10
#define VCODEC_NUV 11
#define VCODEC_RAW 12
+#define VCODEC_X264 13
#define ACODEC_COPY 0
#define ACODEC_PCM 1
@@ -708,7 +709,8 @@
sh_video->vfilter=vf_open_encoder(NULL,"qtvideo",(char *)mux_v); break;
case VCODEC_NUV:
sh_video->vfilter=vf_open_encoder(NULL,"nuv",(char *)mux_v); break;
-
+ case VCODEC_X264:
+ sh_video->vfilter=vf_open_encoder(NULL,"x264",(char *)mux_v); break;
}
if(!mux_v->bih || !sh_video->vfilter){
mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_EncoderOpenFailed);
More information about the MPlayer-dev-eng
mailing list