--- divx4.c 2002/04/28 16:15:51 1.9 +++ divx4.c 2002/05/22 12:40:25 1.12 @@ -32,15 +32,18 @@ * * History: * - * 26.02.2001 fixed dec_csp bugs - * 26.12.2001 xvid_init() support - * 22.12.2001 removed some compiler warnings - * 16.12.2001 inital version; (c)2001 peter ross + * 26.02.2001 fixed dec_csp bugs + * 26.12.2001 xvid_init() support + * 22.12.2001 removed some compiler warnings + * 16.12.2001 inital version; (c)2001 peter ross + * + * $Id: divx4.c,v 1.12 2002/05/22 12:40:25 chl Exp $ * *************************************************************************/ #include #include +#include #include "xvid.h" #include "divx4.h" @@ -72,6 +75,15 @@ } DINST; +typedef struct EINST +{ + struct EINST * next; + + void * handle; + int quality; + +} EINST; + /************************************************************************** * Global data (needed to emulate correctly exported symbols from divx4) *************************************************************************/ @@ -85,26 +97,26 @@ /* The Divx4 instance chainlist */ static DINST * dhead = NULL; +static EINST * ehead = NULL; /* Divx4 quality to XviD encoder motion flag presets */ static int const divx4_motion_presets[7] = { 0, - PMV_QUICKSTOP16, - PMV_EARLYSTOP16, + PMV_EARLYSTOP16 | PMV_ADVANCEDDIAMOND16, + PMV_EARLYSTOP16 | PMV_HALFPELREFINE16, PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | - PMV_EARLYSTOP8 | PMV_HALFPELDIAMOND8, + PMV_EARLYSTOP8 | PMV_HALFPELREFINE8, PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | - PMV_EARLYSTOP8 | PMV_HALFPELDIAMOND8, + PMV_EARLYSTOP8 | PMV_HALFPELREFINE8, - PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | - PMV_EXTSEARCH16 | PMV_EARLYSTOP8 | - PMV_HALFPELREFINE8 | PMV_HALFPELDIAMOND8 + PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EXTSEARCH16 | + PMV_EARLYSTOP8 | PMV_HALFPELREFINE8 }; @@ -115,16 +127,10 @@ XVID_H263QUANT, XVID_H263QUANT | XVID_HALFPEL, XVID_H263QUANT | XVID_INTER4V | XVID_HALFPEL, - XVID_H263QUANT | XVID_INTER4V | XVID_HALFPEL, + XVID_H263QUANT | XVID_INTER4V | XVID_HALFPEL, XVID_H263QUANT | XVID_INTER4V | XVID_HALFPEL }; -/* - * Current divx4 encoder quality - * ToDo : this data should not be shared between encoder instances - */ -static int quality; - /************************************************************************** * Local Prototypes *************************************************************************/ @@ -134,6 +140,10 @@ static DINST * dinst_add(unsigned long key); static void dinst_remove(unsigned long key); +static EINST * einst_find(void *handle); +static EINST * einst_add(void *handle); +static void einst_remove(void *handle); + /* Converts divx4 colorspaces codes to xvid codes */ static int xvid_to_opendivx_dec_csp(int csp); static int xvid_to_opendivx_enc_csp(int csp); @@ -332,6 +342,7 @@ switch(opt) { case ENC_OPT_INIT : { + EINST *ecur; ENC_PARAM * eparam = (ENC_PARAM *)param1; XVID_INIT_PARAM xinit; XVID_ENC_PARAM xparam; @@ -360,18 +371,40 @@ xparam.min_quantizer = eparam->min_quantizer; xparam.max_quantizer = eparam->max_quantizer; xparam.max_key_interval = eparam->max_key_interval; - quality = eparam->quality; /* Create the encoder session */ xerr = encoder_create(&xparam); eparam->handle = xparam.handle; + /* Create an encoder instance in the chainlist */ + if ((ecur = einst_find(xparam.handle)) == NULL) + { + ecur = einst_add(xparam.handle); + + if(ecur == NULL) { + encoder_destroy((Encoder*)xparam.handle); + return ENC_MEMORY; + } + + } + + ecur->quality = eparam->quality; + if(ecur->quality < 0) ecur->quality = 0; + if(ecur->quality > 6) ecur->quality = 6; + break; } case ENC_OPT_RELEASE : { + EINST *ecur; + + if ((ecur = einst_find(handle)) == NULL) + { + return ENC_FAIL; + } + xerr = encoder_destroy((Encoder *) handle); break; } @@ -379,17 +412,23 @@ case ENC_OPT_ENCODE : case ENC_OPT_ENCODE_VBR : { + EINST *ecur; + ENC_FRAME * eframe = (ENC_FRAME *)param1; ENC_RESULT * eresult = (ENC_RESULT *)param2; XVID_ENC_FRAME xframe; XVID_ENC_STATS xstats; + if ((ecur = einst_find(handle)) == NULL) + { + return ENC_FAIL; + } + /* Copy the divx4 info into the xvid structure */ xframe.bitstream = eframe->bitstream; xframe.length = eframe->length; - - xframe.motion = divx4_motion_presets[quality]; - xframe.general = divx4_general_presets[quality]; + xframe.motion = divx4_motion_presets[ecur->quality]; + xframe.general = divx4_general_presets[ecur->quality]; xframe.image = eframe->image; xframe.colorspace = @@ -517,6 +556,77 @@ } } + +/*************************************** + * EINST chainlist helper functions * + ***************************************/ + +/* Find an element in the chainlist according to its handle */ +static EINST * einst_find(void *handle) +{ + EINST * ecur = ehead; + + while (ecur) + { + if (ecur->handle == handle) + { + return ecur; + } + ecur = ecur->next; + } + + return NULL; +} + + +/* Add an element to the chainlist */ +static EINST * einst_add(void *handle) +{ + EINST * enext = ehead; + + ehead = malloc(sizeof(EINST)); + if (ehead == NULL) + { + ehead = enext; + return NULL; + } + + ehead->handle = handle; + ehead->next = enext; + + return ehead; +} + + +/* Remove an elmement from the chainlist */ +static void einst_remove(void *handle) +{ + EINST * ecur = ehead; + + if (ehead == NULL) + { + return; + } + + if (ecur->handle == handle) + { + ehead = ecur->next; + free(ecur); + return; + } + + while (ecur->next) + { + if (ecur->next->handle == handle) + { + EINST * tmp = ecur->next; + ecur->next = tmp->next; + free(tmp); + return; + } + ecur = ecur->next; + } +} /*************************************** * Colorspace code converter * ***************************************/