summaryrefslogtreecommitdiffstats
path: root/core/XvidEnc.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/XvidEnc.c')
-rw-r--r--core/XvidEnc.c170
1 files changed, 170 insertions, 0 deletions
diff --git a/core/XvidEnc.c b/core/XvidEnc.c
new file mode 100644
index 000000000..8f16ad4ba
--- /dev/null
+++ b/core/XvidEnc.c
@@ -0,0 +1,170 @@
+/* $Id: XvidEnc.c,v 1.5 2003/11/05 19:14:37 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 "XvidEnc.h"
+#include "Fifo.h"
+#include "Work.h"
+
+#include <xvid.h>
+
+/* Local prototypes */
+static int XvidEncWork( HBWork * );
+
+struct HBXvidEnc
+{
+ HB_WORK_COMMON_MEMBERS
+
+ HBHandle * handle;
+ HBTitle * title;
+
+ void * xvid;
+ HBBuffer * mpeg4Buffer;
+ int pass;
+};
+
+HBXvidEnc * HBXvidEncInit( HBHandle * handle, HBTitle * title )
+{
+ HBXvidEnc * x;
+ if( !( x = malloc( sizeof( HBXvidEnc ) ) ) )
+ {
+ HBLog( "HBXvidEncInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ x->name = strdup( "XvidEnc" );
+ x->work = XvidEncWork;
+
+ x->handle = handle;
+ x->title = title;
+
+ x->xvid = NULL;
+ x->mpeg4Buffer = NULL;
+ x->pass = 42;
+
+ return x;
+}
+
+void HBXvidEncClose( HBXvidEnc ** _x )
+{
+ HBXvidEnc * x = *_x;
+ free( x );
+ *_x = NULL;
+}
+
+static int XvidEncWork( HBWork * w )
+{
+ HBXvidEnc * x = (HBXvidEnc*) w;
+ HBTitle * title = x->title;
+ HBBuffer * scaledBuffer;
+ HBBuffer * mpeg4Buffer;
+ XVID_ENC_FRAME xframe;
+
+ int didSomething = 0;
+
+ if( x->mpeg4Buffer )
+ {
+ if( HBFifoPush( title->mpeg4Fifo, &x->mpeg4Buffer ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+ }
+
+ if( ( scaledBuffer = HBFifoPop( title->scaledFifo ) ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+
+ /* Init or re-init if needed */
+ if( scaledBuffer->pass != x->pass )
+ {
+ XVID_INIT_PARAM xinit;
+ XVID_ENC_PARAM xparam;
+
+ x->pass = scaledBuffer->pass;;
+
+ HBLog( "HBXvidEnc: opening libxvidcore (pass %d)", x->pass );
+
+ xinit.cpu_flags = 0;
+ xvid_init( NULL, 0, &xinit, NULL );
+
+ xparam.width = title->outWidth;
+ xparam.height = title->outHeight;
+
+ xparam.fincr = title->rateBase;
+ xparam.fbase = title->rate;
+
+ xparam.rc_bitrate = title->bitrate * 1000;
+
+ /* Default values should be ok */
+ xparam.rc_reaction_delay_factor = -1;
+ xparam.rc_averaging_period = -1;
+ xparam.rc_buffer = -1;
+ xparam.max_quantizer = -1;
+ xparam.min_quantizer = -1;
+ xparam.max_key_interval = -1;
+
+ if( xvid_encore( NULL, XVID_ENC_CREATE, &xparam, NULL ) )
+ {
+ HBLog( "HBXvidEnc: xvid_encore() failed" );
+ }
+
+ x->xvid = xparam.handle;
+ }
+
+ /* TODO implement 2-pass encoding */
+ if( x->pass == 1 )
+ {
+ HBPosition( x->handle, scaledBuffer->position );
+ HBBufferClose( &scaledBuffer );
+ return didSomething;
+ }
+
+ mpeg4Buffer = HBBufferInit( title->outWidth *
+ title->outHeight * 3 / 2 );
+ mpeg4Buffer->position = scaledBuffer->position;
+
+ xframe.general = XVID_H263QUANT | XVID_HALFPEL | XVID_INTER4V;
+ xframe.motion = PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 |
+ PMV_EXTSEARCH16 | PMV_EARLYSTOP8 |
+ PMV_HALFPELREFINE8 | PMV_HALFPELDIAMOND8 |
+ PMV_USESQUARES16;
+ xframe.bitstream = mpeg4Buffer->data;
+
+ xframe.image = scaledBuffer->data;
+ xframe.colorspace = XVID_CSP_I420;
+
+ xframe.quant_intra_matrix = NULL;
+ xframe.quant_inter_matrix = NULL;
+ xframe.quant = 0;
+ xframe.intra = -1;
+
+ xframe.hint.hintstream = NULL;
+
+ if( xvid_encore( x->xvid, XVID_ENC_ENCODE, &xframe, NULL ) )
+ {
+ HBLog( "HBXvidEnc: xvid_encore() failed" );
+ }
+
+ mpeg4Buffer->size = xframe.length;
+ mpeg4Buffer->keyFrame = xframe.intra;
+
+ /* Inform the GUI about the current position */
+ HBPosition( x->handle, scaledBuffer->position );
+
+ HBBufferClose( &scaledBuffer );
+ x->mpeg4Buffer = mpeg4Buffer;
+
+ return didSomething;
+}
+