[svn] / trunk / xvidcore / src / divx4.c Repository:
ViewVC logotype

View of /trunk/xvidcore/src/divx4.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 142 - (download) (annotate)
Sat Apr 27 23:51:59 2002 UTC (16 years, 11 months ago) by chl
File size: 9532 byte(s)
added divx4_general_preset to compelety determine quality levels.
/**************************************************************************
 *
 *	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.
 *
 *************************************************************************/

/**************************************************************************
 *
 *	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 <pross@cs.rmit.edu.au>
 *
 *************************************************************************/

#ifndef FREEBSD
#include <malloc.h>
#else
#include <stdlib.h>
#endif
#include <string.h>     // memset

#include "xvid.h"
#include "divx4.h"
#include "decoder.h"
#include "encoder.h"

#define EMULATED_DIVX_VERSION 20011001

// decore


typedef struct DINST
{
	unsigned long key;
	struct DINST * next;

	void * handle;
	XVID_DEC_FRAME xframe;

} DINST;

	
static DINST * dhead = NULL;


DINST * dinst_find(unsigned long key)
{
	DINST * dcur = dhead;

	while (dcur)
	{
		if (dcur->key == key)
		{
			return dcur;
		}
		dcur = dcur->next;
	}

	return NULL;
}


DINST * dinst_add(unsigned long key)
{
	DINST * dnext = dhead;

	dhead = malloc(sizeof(DINST));
	if (dhead == NULL)
	{
		dhead = dnext;
		return NULL;
	}

	dhead->key = key;
	dhead->next = dnext;

	return dhead;
}


void dinst_remove(unsigned long key)
{
	DINST * dcur = dhead;

	if (dhead == NULL)
	{
		return;
	}

	if (dcur->key == key)
	{
		dhead = dcur->next;
		free(dcur);
		return;
	}

	while (dcur->next)
	{
		if (dcur->next->key == key)
		{
			DINST * tmp = dcur->next;
			dcur->next = tmp->next;
			free(tmp);
			return;
		}
		dcur = dcur->next;
	}
}


int xvid_to_opendivx_dec_csp(int csp)
{
	switch(csp)
	{
	case DEC_YV12 :
		return XVID_CSP_YV12;
	case DEC_420 :
		return XVID_CSP_I420;
	case DEC_YUY2 :
		return XVID_CSP_YUY2;
	case DEC_UYVY :
		return XVID_CSP_UYVY;
	case DEC_RGB32 :
		return XVID_CSP_VFLIP | XVID_CSP_RGB32;
	case DEC_RGB24 :
		return XVID_CSP_VFLIP | XVID_CSP_RGB24;
	case DEC_RGB565 :
		return XVID_CSP_VFLIP | XVID_CSP_RGB565;
	case DEC_RGB555 :
		return XVID_CSP_VFLIP | XVID_CSP_RGB555;
	case DEC_RGB32_INV :
		return XVID_CSP_RGB32;
	case DEC_RGB24_INV :
		return XVID_CSP_RGB24;
	case DEC_RGB565_INV :
		return XVID_CSP_RGB565;
	case DEC_RGB555_INV :
		return XVID_CSP_RGB555;
	case DEC_USER :
		return XVID_CSP_USER;    
	default :
		return -1;
	}
}


int decore(unsigned long key, unsigned long opt,
					void * param1, void * param2)
{
	int xerr;

	switch (opt)
	{
	case DEC_OPT_MEMORY_REQS :
		{
			memset(param2, 0, sizeof(DEC_MEM_REQS));
			return DEC_OK;
		}

	case DEC_OPT_INIT :
		{
			DEC_PARAM * dparam = (DEC_PARAM *)param1;
			XVID_INIT_PARAM xinit;
			XVID_DEC_PARAM xparam;
			DINST * dcur = dinst_find(key);
			if (dcur == NULL)
			{
				dcur = dinst_add(key);
			}

			xinit.cpu_flags = 0;
			xvid_init(NULL, 0, &xinit, NULL);

			xparam.width = dparam->x_dim;
			xparam.height = dparam->y_dim;
			dcur->xframe.colorspace = xvid_to_opendivx_dec_csp(dparam->output_format);
				
			xerr = decoder_create(&xparam);

			dcur->handle = xparam.handle;
			
			break;
		}

	case DEC_OPT_RELEASE :
		{
			DINST * dcur = dinst_find(key);
			if (dcur == NULL)
			{
				return DEC_EXIT;
			}
			
			xerr = decoder_destroy(dcur->handle);

			dinst_remove(key);

			break;
		}
	
	case DEC_OPT_SETPP :
		{
			// DEC_SET * dset = (DEC_SET *)param1;
			DINST * dcur = dinst_find(key);
			if (dcur == NULL)
			{
				return DEC_EXIT;
			}

			// dcur->xframe.pp = dset->postproc_level;

			return DEC_OK;
		}

	case DEC_OPT_SETOUT :
		{
			DEC_PARAM * dparam = (DEC_PARAM *)param1;
			DINST * dcur = dinst_find(key);
			if (dcur == NULL)
			{
				return DEC_EXIT;
			}

			dcur->xframe.colorspace = xvid_to_opendivx_dec_csp(dparam->output_format);

			return DEC_OK;
		}
	
	case DEC_OPT_FRAME:
		{
			int csp_tmp = 0;

			DEC_FRAME * dframe = (DEC_FRAME *)param1;
			DINST * dcur = dinst_find(key);
			if (dcur == NULL)
			{
				return DEC_EXIT;
			}

			dcur->xframe.bitstream = dframe->bitstream;
			dcur->xframe.length = dframe->length;
			dcur->xframe.image = dframe->bmp;
			dcur->xframe.stride = dframe->stride;
			
			if (!dframe->render_flag)
			{
				csp_tmp = dcur->xframe.colorspace;
				dcur->xframe.colorspace = XVID_CSP_NULL;
			}
			
			xerr = decoder_decode(dcur->handle, &dcur->xframe);

			if (!dframe->render_flag)
			{
				dcur->xframe.colorspace = csp_tmp;
			}

			break;
		}


	case DEC_OPT_FRAME_311 :
		return DEC_EXIT;


	case DEC_OPT_VERSION:
		return EMULATED_DIVX_VERSION;
	default :
		return DEC_EXIT;
	}


	switch(xerr)
	{
	case XVID_ERR_OK : return DEC_OK;
	case XVID_ERR_MEMORY : return DEC_MEMORY;
	case XVID_ERR_FORMAT : return DEC_BAD_FORMAT;
	default : // case XVID_ERR_FAIL : 
		return DEC_EXIT;
	}
}




// encore

#define FRAMERATE_INCR		1001

int divx4_motion_presets[7] = {
	0, 
	PMV_QUICKSTOP16, 
	PMV_EARLYSTOP16, 
	PMV_EARLYSTOP16 | PMV_HALFPELREFINE16,
	PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EARLYSTOP8 | PMV_HALFPELDIAMOND8,
	PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EARLYSTOP8 | PMV_HALFPELDIAMOND8,
	PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EXTSEARCH16 | PMV_EARLYSTOP8 | PMV_HALFPELREFINE8 | PMV_HALFPELDIAMOND8
};


int divx4_general_presets[7] = {
	0, 
	XVID_H263QUANT, 
	XVID_H263QUANT,
	XVID_H263QUANT | XVID_HALFPEL,
	XVID_H263QUANT | XVID_INTER4V | XVID_HALFPEL,
   	XVID_H263QUANT | XVID_INTER4V | XVID_HALFPEL, 
	XVID_H263QUANT | XVID_INTER4V | XVID_HALFPEL
};

int quality;

int encore(void * handle, int opt, void * param1, void * param2)
{
	int xerr;

	switch(opt)
	{
	case ENC_OPT_INIT :
		{
			ENC_PARAM * eparam = (ENC_PARAM *)param1;
			XVID_INIT_PARAM xinit;
			XVID_ENC_PARAM xparam;

			xinit.cpu_flags = 0;
			xvid_init(NULL, 0, &xinit, NULL);
						
			xparam.width = eparam->x_dim;
			xparam.height = eparam->y_dim;
			if ((eparam->framerate - (int)eparam->framerate) == 0)
			{
				xparam.fincr = 1; 
				xparam.fbase = (int)eparam->framerate;
			}
			else
			{
				xparam.fincr = FRAMERATE_INCR;
				xparam.fbase = (int)(FRAMERATE_INCR * eparam->framerate);
			}
			xparam.rc_bitrate = eparam->bitrate;
			xparam.rc_reaction_delay_factor = 16;
			xparam.rc_averaging_period = 100;
			xparam.rc_buffer = 100;
			xparam.min_quantizer = eparam->min_quantizer;
			xparam.max_quantizer = eparam->max_quantizer;
			xparam.max_key_interval = eparam->max_key_interval;
			quality = eparam->quality;

			xerr = encoder_create(&xparam);

			eparam->handle = xparam.handle;

			break;
		}

	case ENC_OPT_RELEASE :
		{
			xerr = encoder_destroy((Encoder *) handle);
			break;
		}

	case ENC_OPT_ENCODE :
	case ENC_OPT_ENCODE_VBR :
		{
			ENC_FRAME * eframe = (ENC_FRAME *)param1;
			ENC_RESULT * eresult = (ENC_RESULT *)param2;
			XVID_ENC_FRAME xframe;
			XVID_ENC_STATS xstats;

			xframe.bitstream = eframe->bitstream;
			xframe.length = eframe->length;

			xframe.motion = divx4_motion_presets[quality];
			xframe.general = divx4_general_presets[quality];

			xframe.image = eframe->image;
			switch (eframe->colorspace)
			{
			case ENC_CSP_RGB24 : 
				xframe.colorspace = XVID_CSP_VFLIP | XVID_CSP_RGB24;
				break;
			case ENC_CSP_YV12 :
				xframe.colorspace = XVID_CSP_YV12;
				break;
			case ENC_CSP_YUY2 :
				xframe.colorspace = XVID_CSP_YUY2;
				break;
			case ENC_CSP_UYVY :
				xframe.colorspace = XVID_CSP_UYVY;
				break;
			case ENC_CSP_I420 :
				xframe.colorspace = XVID_CSP_I420;
				break;
			}

			if (opt == ENC_OPT_ENCODE_VBR)	
			{
				xframe.intra = eframe->intra;
				xframe.quant = eframe->quant;
			}
			else
			{
				xframe.intra = -1;
				xframe.quant = 0;
			}
			
			xerr = encoder_encode((Encoder *) handle, &xframe, (eresult ? &xstats : NULL) );

			if (eresult)
			{
				eresult->is_key_frame = xframe.intra;
				eresult->quantizer = xstats.quant;
				eresult->total_bits = xframe.length * 8;
				eresult->motion_bits = xstats.hlength * 8;
				eresult->texture_bits = eresult->total_bits - eresult->motion_bits;
			}

			eframe->length = xframe.length;

			break;
		}

	default:
		return ENC_FAIL;
	}

	switch(xerr)
	{
	case XVID_ERR_OK : return ENC_OK;
	case XVID_ERR_MEMORY : return ENC_MEMORY;
	case XVID_ERR_FORMAT : return ENC_BAD_FORMAT;
	default : // case XVID_ERR_FAIL : 
		return ENC_FAIL;
	}
}


No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4