[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