summaryrefslogtreecommitdiffstats
path: root/libhb/encxvid.c
diff options
context:
space:
mode:
Diffstat (limited to 'libhb/encxvid.c')
-rw-r--r--libhb/encxvid.c223
1 files changed, 223 insertions, 0 deletions
diff --git a/libhb/encxvid.c b/libhb/encxvid.c
new file mode 100644
index 000000000..7768f8e12
--- /dev/null
+++ b/libhb/encxvid.c
@@ -0,0 +1,223 @@
+/* $Id: encxvid.c,v 1.10 2005/03/09 23:28:39 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "hb.h"
+
+#include "xvid.h"
+
+int encxvidInit( hb_work_object_t *, hb_job_t * );
+int encxvidWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
+void encxvidClose( hb_work_object_t * );
+
+hb_work_object_t hb_encxvid =
+{
+ WORK_ENCXVID,
+ "MPEG-4 encoder (libxvidcore)",
+ encxvidInit,
+ encxvidWork,
+ encxvidClose
+};
+
+struct hb_work_private_s
+{
+ hb_job_t * job;
+ void * xvid;
+ char filename[1024];
+ int quant;
+ int configDone;
+};
+
+int encxvidInit( hb_work_object_t * w, hb_job_t * job )
+{
+ xvid_gbl_init_t xvid_gbl_init;
+ xvid_enc_create_t create;
+ xvid_plugin_single_t single;
+ xvid_plugin_2pass1_t rc2pass1;
+ xvid_plugin_2pass2_t rc2pass2;
+ xvid_enc_plugin_t plugins[1];
+
+ hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
+ w->private_data = pv;
+
+ pv->job = job;
+
+ memset( pv->filename, 0, 1024 );
+ hb_get_tempory_filename( job->h, pv->filename, "xvid.log" );
+
+ memset( &xvid_gbl_init, 0, sizeof( xvid_gbl_init ) );
+ xvid_gbl_init.version = XVID_VERSION;
+ xvid_global( NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL );
+
+ memset( &create, 0, sizeof( create ) );
+ create.version = XVID_VERSION;
+ create.width = job->width;
+ create.height = job->height;
+ create.zones = NULL;
+ create.num_zones = 0;
+
+ switch( job->pass )
+ {
+ case 0:
+ memset( &single, 0, sizeof( single ) );
+ single.version = XVID_VERSION;
+ if( job->vquality < 0.0 || job->vquality > 1.0 )
+ {
+ /* Rate control */
+ single.bitrate = 1000 * job->vbitrate;
+ pv->quant = 0;
+ }
+ else
+ {
+ /* Constant quantizer */
+ pv->quant = 31 - job->vquality * 30;
+ hb_log( "encxvid: encoding at constant quantizer %d",
+ pv->quant );
+ }
+ plugins[0].func = xvid_plugin_single;
+ plugins[0].param = &single;
+ break;
+
+ case 1:
+ memset( &rc2pass1, 0, sizeof( rc2pass1 ) );
+ rc2pass1.version = XVID_VERSION;
+ rc2pass1.filename = pv->filename;
+ plugins[0].func = xvid_plugin_2pass1;
+ plugins[0].param = &rc2pass1;
+ break;
+
+ case 2:
+ memset( &rc2pass2, 0, sizeof( rc2pass2 ) );
+ rc2pass2.version = XVID_VERSION;
+ rc2pass2.filename = pv->filename;
+ rc2pass2.bitrate = 1000 * job->vbitrate;
+ plugins[0].func = xvid_plugin_2pass2;
+ plugins[0].param = &rc2pass2;
+ break;
+ }
+
+ create.plugins = plugins;
+ create.num_plugins = 1;
+
+ create.num_threads = 0;
+ create.fincr = job->vrate_base;
+ create.fbase = job->vrate;
+ create.max_key_interval = 10 * job->vrate / job->vrate_base;
+ create.max_bframes = 0;
+ create.bquant_ratio = 150;
+ create.bquant_offset = 100;
+ create.frame_drop_ratio = 0;
+ create.global = 0;
+
+ xvid_encore( NULL, XVID_ENC_CREATE, &create, NULL );
+ pv->xvid = create.handle;
+
+ return 0;
+}
+
+/***********************************************************************
+ * Close
+ ***********************************************************************
+ *
+ **********************************************************************/
+void encxvidClose( hb_work_object_t * w )
+{
+ hb_work_private_t * pv = w->private_data;
+
+ if( pv->xvid )
+ {
+ hb_log( "encxvid: closing libxvidcore" );
+ xvid_encore( pv->xvid, XVID_ENC_DESTROY, NULL, NULL);
+ }
+}
+
+/***********************************************************************
+ * Work
+ ***********************************************************************
+ *
+ **********************************************************************/
+int encxvidWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
+ hb_buffer_t ** buf_out )
+{
+ hb_work_private_t * pv = w->private_data;
+ hb_job_t * job = pv->job;
+ xvid_enc_frame_t frame;
+ hb_buffer_t * in = *buf_in, * buf;
+
+ /* Should be way too large */
+ buf = hb_buffer_init( 3 * job->width * job->height / 2 );
+ buf->start = in->start;
+ buf->stop = in->stop;
+
+ memset( &frame, 0, sizeof( frame ) );
+
+ frame.version = XVID_VERSION;
+ frame.bitstream = buf->data;
+ frame.length = -1;
+ frame.input.plane[0] = in->data;
+ frame.input.csp = XVID_CSP_I420;
+ frame.input.stride[0] = job->width;
+ frame.vol_flags = 0;
+ frame.vop_flags = XVID_VOP_HALFPEL | XVID_VOP_INTER4V |
+ XVID_VOP_TRELLISQUANT | XVID_VOP_HQACPRED;
+ if( job->pixel_ratio )
+ {
+ frame.par = XVID_PAR_EXT;
+ frame.par_width = job->pixel_aspect_width;
+ frame.par_height = job->pixel_aspect_height;
+ }
+
+ if( job->grayscale )
+ {
+ frame.vop_flags |= XVID_VOP_GREYSCALE;
+ }
+ frame.type = XVID_TYPE_AUTO;
+ frame.quant = pv->quant;
+ frame.motion = XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 |
+ XVID_ME_EXTSEARCH16 | XVID_ME_ADVANCEDDIAMOND8 |
+ XVID_ME_HALFPELREFINE8 | XVID_ME_EXTSEARCH8 |
+ XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP;
+ frame.quant_intra_matrix = NULL;
+ frame.quant_inter_matrix = NULL;
+
+ buf->size = xvid_encore( pv->xvid, XVID_ENC_ENCODE, &frame, NULL );
+ buf->key = ( frame.out_flags & XVID_KEYFRAME );
+
+ if( !pv->configDone )
+ {
+ int vol_start, vop_start;
+ for( vol_start = 0; ; vol_start++ )
+ {
+ if( buf->data[vol_start] == 0x0 &&
+ buf->data[vol_start+1] == 0x0 &&
+ buf->data[vol_start+2] == 0x1 &&
+ buf->data[vol_start+3] == 0x20 )
+ {
+ break;
+ }
+ }
+ for( vop_start = vol_start + 4; ; vop_start++ )
+ {
+ if( buf->data[vop_start] == 0x0 &&
+ buf->data[vop_start+1] == 0x0 &&
+ buf->data[vop_start+2] == 0x1 &&
+ buf->data[vop_start+3] == 0xB6 )
+ {
+ break;
+ }
+ }
+
+ hb_log( "encxvid: VOL size is %d bytes", vop_start - vol_start );
+ job->config.mpeg4.length = vop_start - vol_start;
+ memcpy( job->config.mpeg4.bytes, &buf->data[vol_start],
+ job->config.mpeg4.length );
+ pv->configDone = 1;
+ }
+
+ *buf_out = buf;
+
+ return HB_WORK_OK;
+}
+