[MPlayer-dev-eng] Re: ve_xvid.c ?
Rémi Guyomarch
rguyom at pobox.com
Thu Sep 19 23:10:57 CEST 2002
On Thu, Sep 19, 2002 at 09:44:52PM +0200, Arpi wrote:
> Hi,
>
> Anyone is working on native xvid encoding?
I'm not working on it, but I have a very rough xvid support
working. Patches & files attached.
Warning ! This code has a lot of quirks :
- works with CVS-current mplayer/mencoder *and* CVS-current XViD
- you need to configure mplayer/mencoder with
./configure --with-extraincdir=/foo/bar/xvid/xvidcore/src/ \
--with-xvidcore=/foo/bar/xvid/xvidcore/build/generic/libxvidcore.a
- no support for 2-pass mode
- no compile-time (./configure) detection
- lacks a few #ifdef XVID_NATIVESUPPORT here and there
- not very well tested
(I mean, I can encode mplayer-playable [with "-vc xvid"] .avi files
with this code, but I didn't checked on Windows)
Enjoy ;)
Btw, during the limited testing I did, this codec seems to be ~3 times
slower than libavcodec on my XP 1800+ :-/
--
Rémi
-------------- next part --------------
Index: cfg-mencoder.h
===================================================================
RCS file: /cvsroot/mplayer/main/cfg-mencoder.h,v
retrieving revision 1.50
diff -u -u -r1.50 cfg-mencoder.h
--- cfg-mencoder.h 29 Aug 2002 20:50:48 -0000 1.50
+++ cfg-mencoder.h 19 Sep 2002 21:16:26 -0000
@@ -19,6 +19,7 @@
#ifdef HAVE_DIVX4ENCORE
extern struct config divx4opts_conf[];
#endif
+extern struct config xvidopts_conf[];
#ifdef HAVE_MP3LAME
struct config lameopts_conf[]={
@@ -49,6 +50,7 @@
{"copy", &out_video_codec, CONF_TYPE_FLAG, 0, 0, VCODEC_COPY, NULL},
{"frameno", &out_video_codec, CONF_TYPE_FLAG, 0, 0, VCODEC_FRAMENO, NULL},
{"divx4", &out_video_codec, CONF_TYPE_FLAG, 0, 0, VCODEC_DIVX4, NULL},
+ {"xvid", &out_video_codec, CONF_TYPE_FLAG, 0, 0, VCODEC_XVID, NULL},
// {"raw", &out_video_codec, CONF_TYPE_FLAG, 0, 0, VCODEC_RAW, NULL},
{"lavc", &out_video_codec, CONF_TYPE_FLAG, 0, 0, VCODEC_LIBAVCODEC, NULL},
// {"null", &out_video_codec, CONF_TYPE_FLAG, 0, 0, VCODEC_NULL, NULL},
@@ -156,6 +158,7 @@
#ifdef HAVE_DIVX4ENCORE
{"divx4opts", divx4opts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
#endif
+ {"xvidopts", xvidopts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
#ifdef HAVE_MP3LAME
{"lameopts", lameopts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
#endif
Index: mencoder.c
===================================================================
RCS file: /cvsroot/mplayer/main/mencoder.c,v
retrieving revision 1.159
diff -u -u -r1.159 mencoder.c
--- mencoder.c 14 Sep 2002 10:47:34 -0000 1.159
+++ mencoder.c 19 Sep 2002 21:16:32 -0000
@@ -6,6 +6,7 @@
#define VCODEC_RAWRGB 6
#define VCODEC_VFW 7
#define VCODEC_LIBDV 8
+#define VCODEC_XVID 9
#define ACODEC_COPY 0
#define ACODEC_PCM 1
@@ -651,6 +652,8 @@
sh_video->vfilter=vf_open_encoder(NULL,"vfw",(char *)mux_v); break;
case VCODEC_LIBDV:
sh_video->vfilter=vf_open_encoder(NULL,"libdv",(char *)mux_v); break;
+ case VCODEC_XVID:
+ sh_video->vfilter=vf_open_encoder(NULL,"xvid",(char *)mux_v); break;
}
if(!mux_v->bih || !sh_video->vfilter){
mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_EncoderOpenFailed);
Index: libmpcodecs/Makefile
===================================================================
RCS file: /cvsroot/mplayer/main/libmpcodecs/Makefile,v
retrieving revision 1.61
diff -u -u -r1.61 Makefile
--- libmpcodecs/Makefile 10 Sep 2002 23:18:31 -0000 1.61
+++ libmpcodecs/Makefile 19 Sep 2002 21:16:32 -0000
@@ -7,7 +7,7 @@
AUDIO_SRCS=dec_audio.c ad.c ad_liba52.c ad_acm.c ad_alaw.c ad_dk3adpcm.c ad_dshow.c ad_dvdpcm.c ad_ffmpeg.c ad_hwac3.c ad_imaadpcm.c ad_mp3lib.c ad_msadpcm.c ad_pcm.c ad_roqaudio.c ad_msgsm.c ad_faad.c ad_libvorbis.c ad_libmad.c ad_realaud.c ad_libdv.c
VIDEO_SRCS=dec_video.c vd.c vd_null.c vd_realvid.c vd_cinepak.c vd_qtrpza.c vd_ffmpeg.c vd_dshow.c vd_vfw.c vd_vfwex.c vd_odivx.c vd_divx4.c vd_raw.c vd_xanim.c vd_msvidc.c vd_fli.c vd_qtrle.c vd_qtsmc.c vd_roqvideo.c vd_cyuv.c vd_nuv.c vd_libmpeg2.c vd_msrle.c vd_huffyuv.c vd_mpegpes.c vd_svq1.c vd_xvid.c vd_libdv.c vd_lcl.c vd_mtga.c
VFILTER_SRCS=vf.c vf_vo.c vf_crop.c vf_expand.c vf_pp.c vf_scale.c vf_format.c vf_yuy2.c vf_flip.c vf_rgb2bgr.c vf_rotate.c vf_mirror.c vf_palette.c vf_lavc.c vf_dvbscale.c vf_cropdetect.c vf_test.c vf_noise.c vf_yvu9.c vf_rectangle.c vf_lavcdeint.c vf_eq.c vf_halfpack.c vf_dint.c
-ENCODER_SRCS=ve.c ve_divx4.c ve_lavc.c ve_vfw.c ve_rawrgb.c ve_libdv.c
+ENCODER_SRCS=ve.c ve_divx4.c ve_lavc.c ve_vfw.c ve_rawrgb.c ve_libdv.c ve_xvid.c
NATIVE_SRCS=native/RTjpegN.c native/cinepak.c native/cyuv.c native/fli.c native/minilzo.c native/msvidc.c native/nuppelvideo.c native/qtrle.c native/qtrpza.c native/qtsmc.c native/roqav.c native/xa_gsm.c native/svq1.c
ifeq ($(FAME),yes)
Index: libmpcodecs/ve.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpcodecs/ve.c,v
retrieving revision 1.3
diff -u -u -r1.3 ve.c
--- libmpcodecs/ve.c 13 Apr 2002 19:14:31 -0000 1.3
+++ libmpcodecs/ve.c 19 Sep 2002 21:16:32 -0000
@@ -14,6 +14,7 @@
extern vf_info_t ve_info_vfw;
extern vf_info_t ve_info_rawrgb;
extern vf_info_t ve_info_libdv;
+extern vf_info_t ve_info_xvid;
static vf_info_t* encoder_list[]={
#ifdef HAVE_DIVX4ENCORE
@@ -29,6 +30,7 @@
&ve_info_libdv,
#endif
&ve_info_rawrgb,
+ &ve_info_xvid,
NULL
};
-------------- next part --------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../config.h"
#include "../mp_msg.h"
#define HAVE_XVIDENCORE
#ifdef HAVE_XVIDENCORE
#include "codec-cfg.h"
#include "stream.h"
#include "demuxer.h"
#include "stheader.h"
#include "aviwrite.h"
#include "img_format.h"
#include "mp_image.h"
#include "vf.h"
//===========================================================================//
void mencoder_write_chunk( aviwrite_stream_t *s, int len, unsigned int flags );
#include <xvid.h>
#define XVID_API_VERSION_NEEDED ((2 << 16) | (1))
#if (API_VERSION != XVID_API_VERSION_NEEDED)
#error "XViD version change detected, can't compile"
#endif
#include "cfgparser.h"
static int xvid_bitrate;
static int xvid_rc_averaging_period;
static int xvid_rc_reaction_delay_factor;
static int xvid_rc_buffer;
static int xvid_min_quantizer;
static int xvid_max_quantizer;
static int xvid_max_key_interval;
static int xvid_quality;
struct config xvidopts_conf[]={
{"bitrate", &xvid_bitrate, CONF_TYPE_INT, CONF_RANGE, 4, 24000000, NULL},
{"rc_reaction_delay_factor", &xvid_rc_reaction_delay_factor, CONF_TYPE_INT, 0,0,0, NULL},
{"rc_averaging_period", &xvid_rc_averaging_period, CONF_TYPE_INT, 0,0,0, NULL},
{"rc_buffer", &xvid_rc_buffer, CONF_TYPE_INT, 0,0,0, NULL},
{"min_quant", &xvid_min_quantizer, CONF_TYPE_INT, CONF_RANGE,1,31, NULL},
{"max_quant", &xvid_max_quantizer, CONF_TYPE_INT, CONF_RANGE,1,31, NULL},
{"key", &xvid_max_key_interval, CONF_TYPE_INT, CONF_MIN,0,0, NULL},
{"q", &xvid_quality, CONF_TYPE_INT, CONF_RANGE, 0, 6, NULL},
{"help", "TODO: xvidopts help!\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
{NULL, NULL, 0, 0, 0, 0, NULL}
};
static int motion_presets[7] = {
0, // Q 0
PMV_EARLYSTOP16, // Q 1
PMV_EARLYSTOP16, // Q 2
PMV_EARLYSTOP16 | PMV_HALFPELREFINE16, // Q 3
PMV_EARLYSTOP16 | PMV_HALFPELREFINE16, // Q 4
PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EARLYSTOP8 // Q 5
| PMV_HALFPELREFINE8,
PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EXTSEARCH16 // Q 6
| PMV_USESQUARES16 | PMV_EARLYSTOP8 | PMV_HALFPELREFINE8
};
static int general_presets[7] = {
XVID_H263QUANT, /* or use XVID_MPEGQUANT */ // Q 0
XVID_MPEGQUANT, // Q 1
XVID_H263QUANT, // Q 2
XVID_H263QUANT | XVID_HALFPEL, // Q 3
XVID_H263QUANT | XVID_HALFPEL | XVID_INTER4V, // Q 4
XVID_H263QUANT | XVID_HALFPEL | XVID_INTER4V, // Q 5
XVID_H263QUANT | XVID_HALFPEL | XVID_INTER4V }; // Q 6
struct vf_priv_s {
aviwrite_stream_t* mux;
XVID_ENC_PARAM enc_param;
XVID_ENC_FRAME enc_frame;
XVID_ENC_STATS enc_stats;
XVID_INIT_PARAM init_param;
void *handle;
FILE *stats_file;
int frame_count;
};
#define mux_v (vf->priv->mux)
static int config(struct vf_instance_s* vf,
int width, int height, int d_width, int d_height,
unsigned int flags, unsigned int outfmt){
int xerr;
mux_v->bih->biWidth = width;
mux_v->bih->biHeight = height;
mux_v->bih->biSizeImage = mux_v->bih->biWidth * mux_v->bih->biHeight * 3;
printf("videocodec: xvid (%dx%d fourcc=%x [%.4s])\n",
mux_v->bih->biWidth, mux_v->bih->biHeight, mux_v->bih->biCompression,
(char *)&mux_v->bih->biCompression);
// check input values and set some useful defaults
if( !xvid_bitrate ) xvid_bitrate = 800000;
else if( xvid_bitrate <= 16000 ) xvid_bitrate *= 1000;
if( !xvid_quality ) xvid_quality = 4;
if( !xvid_min_quantizer ) xvid_min_quantizer = 2;
if( !xvid_max_quantizer ) xvid_max_quantizer = 15;
if( !xvid_max_key_interval )
xvid_max_key_interval = (int)(10.0 * (float)mux_v->h.dwRate / mux_v->h.dwScale);
// initialise XViD
vf->priv->init_param.cpu_flags = 0; // FIXME: use mencoder values
xvid_init( NULL, 0, &vf->priv->init_param, NULL );
if( vf->priv->init_param.api_version != API_VERSION ) {
mp_msg( MSGT_MENCODER, MSGL_ERR,
"XViD: API version mismatch, header = %04x, library = %04x\n",
API_VERSION, vf->priv->init_param.api_version );
return 0;
}
// create a new encoding instance
vf->priv->enc_param.width = width;
vf->priv->enc_param.height = height;
vf->priv->enc_param.fbase = mux_v->h.dwRate;
vf->priv->enc_param.fincr = mux_v->h.dwScale;
vf->priv->enc_param.min_quantizer = xvid_min_quantizer;
vf->priv->enc_param.max_quantizer = xvid_max_quantizer;
vf->priv->enc_param.rc_bitrate = xvid_bitrate;
vf->priv->enc_param.max_key_interval = xvid_max_key_interval;
vf->priv->enc_param.rc_averaging_period = xvid_rc_averaging_period;
vf->priv->enc_param.rc_reaction_delay_factor = xvid_rc_reaction_delay_factor;
vf->priv->enc_param.rc_buffer = xvid_rc_buffer;
xerr = xvid_encore( &vf->priv->handle, XVID_ENC_CREATE, &vf->priv->enc_param, NULL );
if( xerr != XVID_ERR_OK ) {
mp_msg( MSGT_MENCODER, MSGL_ERR, "XViD: initialisation error = %d\n", xerr );
return 0;
}
// pre-fill various things used in the actual encoding
// FIXME: check if RGB24 & BGR24 shoud be mapped to the same
// xvid colospace
switch(outfmt){
case IMGFMT_YV12: vf->priv->enc_frame.colorspace = XVID_CSP_YV12; break;
case IMGFMT_IYUV:
case IMGFMT_I420: vf->priv->enc_frame.colorspace = XVID_CSP_I420; break;
case IMGFMT_YUY2: vf->priv->enc_frame.colorspace = XVID_CSP_YUY2; break;
case IMGFMT_UYVY: vf->priv->enc_frame.colorspace = XVID_CSP_UYVY; break;
case IMGFMT_RGB24:
case IMGFMT_BGR24: vf->priv->enc_frame.colorspace = XVID_CSP_RGB24; break;
default:
mp_msg( MSGT_MENCODER, MSGL_ERR, "xvid: unsupported picture format (%s)!\n",
vo_format_name( outfmt ) );
return 0;
}
vf->priv->enc_frame.general = general_presets[ xvid_quality ];
vf->priv->enc_frame.motion = motion_presets[ xvid_quality ];
vf->priv->enc_frame.quant_intra_matrix = NULL;
vf->priv->enc_frame.quant_inter_matrix = NULL;
vf->priv->frame_count = 0;
// FIXME: implement 2-pass encoding
// FIXME: handle errors here
vf->priv->stats_file = fopen( "xvid_stats.txt", "wt" );
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){
// FIXME: check if IMGFMT_I420 is really supported without conversion
case IMGFMT_YV12:
case IMGFMT_IYUV:
case IMGFMT_I420:
return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW; // no conversion
case IMGFMT_YUY2:
case IMGFMT_UYVY:
return VFCAP_CSP_SUPPORTED; // conversion
case IMGFMT_RGB24:
case IMGFMT_BGR24:
// FIXME: check that
return VFCAP_CSP_SUPPORTED | VFCAP_FLIPPED; // conversion+flipped
}
return 0;
}
static void put_image( struct vf_instance_s* vf, mp_image_t *mpi ) {
int xerr;
// FIXME: implement 2-pass code
// FIXME: use HINTEDMV in pass 2
vf->priv->enc_frame.image = mpi->planes[0];
vf->priv->enc_frame.bitstream = mux_v->buffer;
vf->priv->enc_frame.length = mux_v->buffer_size;
vf->priv->enc_frame.quant = 0;
vf->priv->enc_frame.intra = -1;
xerr = xvid_encore( vf->priv->enc_param.handle, XVID_ENC_ENCODE, &vf->priv->enc_frame, &vf->priv->enc_stats );
if( xerr == XVID_ERR_OK ) {
if( vf->priv->stats_file )
fprintf( vf->priv->stats_file,
"frame:%d q:%d slen:%d qlen:%d kblks:%d mblks:%d ublks:%d type:%c\n",
vf->priv->frame_count, vf->priv->enc_stats.quant, vf->priv->enc_stats.hlength * 8,
(vf->priv->enc_frame.length - vf->priv->enc_stats.hlength) * 8,
vf->priv->enc_stats.kblks, vf->priv->enc_stats.mblks, vf->priv->enc_stats.ublks,
vf->priv->enc_frame.intra ? 'I':'P' );
vf->priv->frame_count++;
mencoder_write_chunk( mux_v, vf->priv->enc_frame.length, vf->priv->enc_frame.intra ? 0x10 : 0 );
} else
mp_msg( MSGT_MENCODER, MSGL_ERR, "XViD: encoding error = %d\n", xerr );
}
static void uninit(struct vf_instance_s* vf) {
xvid_encore( vf->priv->handle, XVID_ENC_DESTROY, NULL, NULL );
if( vf->priv->stats_file )
fclose( vf->priv->stats_file );
}
//===========================================================================//
static int vf_open( vf_instance_t *vf, char* args ) {
vf->uninit = uninit;
vf->config = config;
vf->control = control;
vf->query_format = query_format;
vf->put_image = put_image;
vf->priv = malloc( sizeof( struct vf_priv_s ) );
memset( vf->priv, 0, sizeof( struct vf_priv_s ) );
vf->priv->mux = (aviwrite_stream_t*)args;
mux_v->bih = malloc( sizeof(BITMAPINFOHEADER ) );
mux_v->bih->biSize = sizeof( BITMAPINFOHEADER );
mux_v->bih->biWidth = 0;
mux_v->bih->biHeight = 0;
mux_v->bih->biPlanes = 1;
mux_v->bih->biBitCount = 24;
mux_v->bih->biCompression = mmioFOURCC( 'X','V','I','D' );
return 1;
}
vf_info_t ve_info_xvid = {
"xvid encoder",
"xvid",
"Rémi Guyomarch",
"for internal use by mencoder",
vf_open
};
//===========================================================================//
#endif
More information about the MPlayer-dev-eng
mailing list