--- divx4.c 2002/04/28 20:03:14 1.10 +++ divx4.c 2002/06/09 23:05:35 1.13 @@ -1,48 +1,49 @@ /************************************************************************** * - * XVID MPEG-4 VIDEO CODEC - * OpenDivx API wrapper + * XVID MPEG-4 VIDEO CODEC + * - OpenDivx API wrapper - * - * This program is an implementation of a part of one or more MPEG-4 - * Video tools as specified in ISO/IEC 14496-2 standard. Those intending - * to use this software module in hardware or software products are - * advised that its use may infringe existing patents or copyrights, and - * any such use would be at such party's own risk. The original - * developer of this software module and his/her company, and subsequent - * editors and their companies, will have no liability for use of this - * software or modifications or derivatives thereof. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * This program is an implementation of a part of one or more MPEG-4 + * Video tools as specified in ISO/IEC 14496-2 standard. Those intending + * to use this software module in hardware or software products are + * advised that its use may infringe existing patents or copyrights, and + * any such use would be at such party's own risk. The original + * developer of this software module and his/her company, and subsequent + * editors and their companies, will have no liability for use of this + * software or modifications or derivatives thereof. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY 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., 675 Mass Ave, Cambridge, MA 02139, USA. * *************************************************************************/ /************************************************************************** * - * History: + * 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.10 2002/04/28 20:03:14 edgomez Exp $ + * $Id: divx4.c,v 1.13 2002/06/09 23:05:35 edgomez Exp $ * *************************************************************************/ #include #include +#include #include "xvid.h" #include "divx4.h" @@ -74,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) *************************************************************************/ @@ -87,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 }; @@ -117,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 *************************************************************************/ @@ -136,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); @@ -334,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; @@ -362,36 +371,66 @@ 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; + } + + einst_remove(handle); xerr = encoder_destroy((Encoder *) handle); + break; } 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 = @@ -519,6 +558,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 * ***************************************/