[svn] / branches / dev-api-4 / xvidcore / src / utils / mbtransquant.c Repository:
ViewVC logotype

View of /branches/dev-api-4/xvidcore/src/utils/mbtransquant.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 914 - (download) (annotate)
Mon Mar 10 00:38:49 2003 UTC (21 years ago) by edgomez
File size: 22297 byte(s)
2003-03-10 00:36:15 GMT	Edouard Gomez <ed.gomez@free.fr>	patch-4

    Summary:
      Adds extended stats support even for bframes in xvidcore.
    Revision:
      xvidcore--devapi4--1.0--patch-4

    This patch enables core extended stats support even for bframes. It
    modifies the way the MBTransQuantBVOP function does its work. It used
    to not dequant, idct the MB because bframes are never used as reference
    frames. However if we want to compute stats, then we must perform these
    inverse transformations.

    modified files:
     src/encoder.c src/utils/mbfunctions.h src/utils/mbtransquant.c
 /******************************************************************************
  *                                                                            *
  *  This file is part of XviD, a free MPEG-4 video encoder/decoder            *
  *                                                                            *
  *  XviD 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.                                     *
  *                                                                            *
  *  XviD 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.                                       *
  *                                                                            *
  *  XviD 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA  *
  *                                                                            *
  ******************************************************************************/

 /******************************************************************************
  *                                                                            *
  *  mbtransquant.c                                                            *
  *                                                                            *
  *  Copyright (C) 2001 - Peter Ross <pross@cs.rmit.edu.au>                    *
  *  Copyright (C) 2001 - Michael Militzer <isibaar@xvid.org>                  *
  *                                                                            *
  *  For more information visit the XviD homepage: http://www.xvid.org         *
  *                                                                            *
  ******************************************************************************/

 /******************************************************************************
  *                                                                            *
  *  Revision history:                                                         *
  *                                                                            *
  *  29.03.2002 interlacing speedup - used transfer strides instead of		   *
  *             manual field-to-frame conversion							   *
  *  26.03.2002 interlacing support - moved transfers outside loops			   *
  *  22.12.2001 get_dc_scaler() moved to common.h							   *
  *  19.11.2001 introduced coefficient thresholding (Isibaar)                  *
  *  17.11.2001 initial version                                                *
  *                                                                            *
  ******************************************************************************/

#include <string.h>

#include "../portab.h"
#include "mbfunctions.h"

#include "../global.h"
#include "mem_transfer.h"
#include "timer.h"
#include "../dct/fdct.h"
#include "../dct/idct.h"
#include "../quant/quant_mpeg4.h"
#include "../quant/quant_h263.h"
#include "../encoder.h"

#include "../image/reduced.h"

MBFIELDTEST_PTR MBFieldTest;

#define TOOSMALL_LIMIT 	1	/* skip blocks having a coefficient sum below this value */

void
MBTransQuantIntra(const MBParam * pParam,
				  FRAMEINFO * frame,
				  MACROBLOCK * pMB,
				  const uint32_t x_pos,
				  const uint32_t y_pos,
				  int16_t data[6 * 64],
				  int16_t qcoeff[6 * 64])
{

	uint32_t stride = pParam->edged_width;
	uint32_t stride2 = stride / 2;
	uint32_t next_block = stride * ((frame->vop_flags & XVID_REDUCED)?16:8);
	uint32_t i;
	uint32_t iQuant = frame->quant;
	uint8_t *pY_Cur, *pU_Cur, *pV_Cur;
	IMAGE *pCurrent = &frame->image;

	start_timer();
	if ((frame->vop_flags & XVID_REDUCED))
	{
		pY_Cur = pCurrent->y + (y_pos << 5) * stride + (x_pos << 5);
		pU_Cur = pCurrent->u + (y_pos << 4) * stride2 + (x_pos << 4);
		pV_Cur = pCurrent->v + (y_pos << 4) * stride2 + (x_pos << 4);

		filter_18x18_to_8x8(&data[0 * 64], pY_Cur, stride);
		filter_18x18_to_8x8(&data[1 * 64], pY_Cur + 16, stride);
		filter_18x18_to_8x8(&data[2 * 64], pY_Cur + next_block, stride);
		filter_18x18_to_8x8(&data[3 * 64], pY_Cur + next_block + 16, stride);
		filter_18x18_to_8x8(&data[4 * 64], pU_Cur, stride2);
		filter_18x18_to_8x8(&data[5 * 64], pV_Cur, stride2);
	}else{
		pY_Cur = pCurrent->y + (y_pos << 4) * stride + (x_pos << 4);
		pU_Cur = pCurrent->u + (y_pos << 3) * stride2 + (x_pos << 3);
		pV_Cur = pCurrent->v + (y_pos << 3) * stride2 + (x_pos << 3);

		transfer_8to16copy(&data[0 * 64], pY_Cur, stride);
		transfer_8to16copy(&data[1 * 64], pY_Cur + 8, stride);
		transfer_8to16copy(&data[2 * 64], pY_Cur + next_block, stride);
		transfer_8to16copy(&data[3 * 64], pY_Cur + next_block + 8, stride);
		transfer_8to16copy(&data[4 * 64], pU_Cur, stride2);
		transfer_8to16copy(&data[5 * 64], pV_Cur, stride2);
	}
	stop_transfer_timer();

	/* XXX: rrv+interlacing is buggy */
	start_timer();
	pMB->field_dct = 0;
	if ((frame->vol_flags & XVID_INTERLACING) &&
		(x_pos>0) && (x_pos<pParam->mb_width-1) &&
		(y_pos>0) && (y_pos<pParam->mb_height-1)) {
		pMB->field_dct = MBDecideFieldDCT(data);
	}
	stop_interlacing_timer();

	for (i = 0; i < 6; i++) {
		uint32_t iDcScaler = get_dc_scaler(iQuant, i < 4);

		start_timer();
		fdct(&data[i * 64]);
		stop_dct_timer();

		if (!(pParam->vol_flags & XVID_MPEGQUANT)) {
			start_timer();
			quant_intra(&qcoeff[i * 64], &data[i * 64], iQuant, iDcScaler);
			stop_quant_timer();
		} else {
			start_timer();
			quant4_intra(&qcoeff[i * 64], &data[i * 64], iQuant, iDcScaler);
			stop_quant_timer();
		}

		/* speedup: dont decode when encoding only ivops */
		if (pParam->iMaxKeyInterval != 1 || pParam->max_bframes > 0)
		{
			if (!(pParam->vol_flags & XVID_MPEGQUANT)) {
				start_timer();
				dequant_intra(&data[i * 64], &qcoeff[i * 64], iQuant, iDcScaler);
				stop_iquant_timer();
			} else {
				start_timer();
				dequant4_intra(&data[i * 64], &qcoeff[i * 64], iQuant, iDcScaler);
				stop_iquant_timer();
			}

			start_timer();
			idct(&data[i * 64]);
			stop_idct_timer();
		}
	}

	/* speedup: dont decode when encoding only ivops */
	if (pParam->iMaxKeyInterval != 1 || pParam->max_bframes > 0)
	{

		if (pMB->field_dct) {
			next_block = stride;
			stride *= 2;
		}

		start_timer();
		if ((frame->vop_flags & XVID_REDUCED))
		{
			copy_upsampled_8x8_16to8(pY_Cur, &data[0 * 64], stride);
			copy_upsampled_8x8_16to8(pY_Cur + 16, &data[1 * 64], stride);
			copy_upsampled_8x8_16to8(pY_Cur + next_block, &data[2 * 64], stride);
			copy_upsampled_8x8_16to8(pY_Cur + next_block + 16, &data[3 * 64], stride);
			copy_upsampled_8x8_16to8(pU_Cur, &data[4 * 64], stride2);
			copy_upsampled_8x8_16to8(pV_Cur, &data[5 * 64], stride2);

		}else{
			transfer_16to8copy(pY_Cur, &data[0 * 64], stride);
			transfer_16to8copy(pY_Cur + 8, &data[1 * 64], stride);
			transfer_16to8copy(pY_Cur + next_block, &data[2 * 64], stride);
			transfer_16to8copy(pY_Cur + next_block + 8, &data[3 * 64], stride);
			transfer_16to8copy(pU_Cur, &data[4 * 64], stride2);
			transfer_16to8copy(pV_Cur, &data[5 * 64], stride2);
		}
		stop_transfer_timer();
	}

}


uint8_t
MBTransQuantInter(const MBParam * pParam,
				  FRAMEINFO * frame,
				  MACROBLOCK * pMB,
				  const uint32_t x_pos,
				  const uint32_t y_pos,
				  int16_t data[6 * 64],
				  int16_t qcoeff[6 * 64])
{

	uint32_t stride = pParam->edged_width;
	uint32_t stride2 = stride / 2;
	uint32_t next_block = stride * ((frame->vop_flags & XVID_REDUCED)?16:8);
	uint32_t i;
	uint32_t iQuant = frame->quant;
	uint8_t *pY_Cur, *pU_Cur, *pV_Cur;
	uint8_t cbp = 0;
	uint32_t sum;
	IMAGE *pCurrent = &frame->image;

	if ((frame->vop_flags & XVID_REDUCED))
	{
		pY_Cur = pCurrent->y + (y_pos << 5) * stride + (x_pos << 5);
		pU_Cur = pCurrent->u + (y_pos << 4) * stride2 + (x_pos << 4);
		pV_Cur = pCurrent->v + (y_pos << 4) * stride2 + (x_pos << 4);
	}else{
		pY_Cur = pCurrent->y + (y_pos << 4) * stride + (x_pos << 4);
		pU_Cur = pCurrent->u + (y_pos << 3) * stride2 + (x_pos << 3);
		pV_Cur = pCurrent->v + (y_pos << 3) * stride2 + (x_pos << 3);
	}

	start_timer();
	pMB->field_dct = 0;
	if ((frame->vol_flags & XVID_INTERLACING) &&
		(x_pos>0) && (x_pos<pParam->mb_width-1) &&
		(y_pos>0) && (y_pos<pParam->mb_height-1)) {
		pMB->field_dct = MBDecideFieldDCT(data);
	}
	stop_interlacing_timer();

	for (i = 0; i < 6; i++) {
		uint32_t increase_limit = (iQuant == 1) ? 1 : 0;

		/* 
		 *  no need to transfer 8->16-bit
		 * (this is performed already in motion compensation) 
		 */
		start_timer();
		fdct(&data[i * 64]);
		stop_dct_timer();

		if (!(pParam->vol_flags & XVID_MPEGQUANT)) {
			start_timer();
			sum = quant_inter(&qcoeff[i * 64], &data[i * 64], iQuant);
			stop_quant_timer();
		} else {
			start_timer();
			sum = quant4_inter(&qcoeff[i * 64], &data[i * 64], iQuant);
			stop_quant_timer();
		}

		if ((sum >= TOOSMALL_LIMIT + increase_limit) || (qcoeff[i*64] != 0) ||
			(qcoeff[i*64+1] != 0) || (qcoeff[i*64+8] != 0)) {

			if (!(pParam->vol_flags & XVID_MPEGQUANT)) {
				start_timer();
				dequant_inter(&data[i * 64], &qcoeff[i * 64], iQuant);
				stop_iquant_timer();
			} else {
				start_timer();
				dequant4_inter(&data[i * 64], &qcoeff[i * 64], iQuant);
				stop_iquant_timer();
			}

			cbp |= 1 << (5 - i);

			start_timer();
			idct(&data[i * 64]);
			stop_idct_timer();
		}
	}

	if (pMB->field_dct) {
		next_block = stride;
		stride *= 2;
	}

	start_timer();
	if ((frame->vop_flags & XVID_REDUCED))
	{
		if (cbp & 32)
			add_upsampled_8x8_16to8(pY_Cur, &data[0 * 64], stride);
		if (cbp & 16)
			add_upsampled_8x8_16to8(pY_Cur + 16, &data[1 * 64], stride);
		if (cbp & 8)
			add_upsampled_8x8_16to8(pY_Cur + next_block, &data[2 * 64], stride);
		if (cbp & 4)
			add_upsampled_8x8_16to8(pY_Cur + 16 + next_block, &data[3 * 64], stride);
		if (cbp & 2)
			add_upsampled_8x8_16to8(pU_Cur, &data[4 * 64], stride2);
		if (cbp & 1)
			add_upsampled_8x8_16to8(pV_Cur, &data[5 * 64], stride2);
	}else{
		if (cbp & 32)
			transfer_16to8add(pY_Cur, &data[0 * 64], stride);
		if (cbp & 16)
			transfer_16to8add(pY_Cur + 8, &data[1 * 64], stride);
		if (cbp & 8)
			transfer_16to8add(pY_Cur + next_block, &data[2 * 64], stride);
		if (cbp & 4)
			transfer_16to8add(pY_Cur + next_block + 8, &data[3 * 64], stride);
		if (cbp & 2)
			transfer_16to8add(pU_Cur, &data[4 * 64], stride2);
		if (cbp & 1)
			transfer_16to8add(pV_Cur, &data[5 * 64], stride2);
	}
	stop_transfer_timer();

	return cbp;

}

void 
MBTransQuantIntra2(const MBParam * pParam,
				  FRAMEINFO * frame,
				  MACROBLOCK * pMB,
				  const uint32_t x_pos,
				  const uint32_t y_pos,
				  int16_t data[6 * 64],
				  int16_t qcoeff[6 * 64])
{
	MBTrans(pParam,frame,pMB,x_pos,y_pos,data);
	MBfDCT(pParam,frame,pMB,data);
	MBQuantIntra(pParam,frame,pMB,data,qcoeff);
	MBDeQuantIntra(pParam,frame->quant,data,qcoeff);
	MBiDCT(data,0x3F);
	MBTransAdd(pParam,frame,pMB,x_pos,y_pos,data,0x3F);
}


uint8_t
MBTransQuantInter2(const MBParam * pParam,
				  FRAMEINFO * frame,
				  MACROBLOCK * pMB,
				  const uint32_t x_pos,
				  const uint32_t y_pos,
				  int16_t data[6 * 64],
				  int16_t qcoeff[6 * 64])
{
	uint8_t cbp;
	
/* there is no MBTrans for Inter block, that's done in motion compensation already */

	MBfDCT(pParam,frame,pMB,data);
	cbp = MBQuantInter(pParam,frame->quant,data,qcoeff);
	MBDeQuantInter(pParam,frame->quant,data,qcoeff,cbp);
	MBiDCT(data,cbp);
	MBTransAdd(pParam,frame,pMB,x_pos,y_pos,data,cbp);
	
	return cbp;
}

uint8_t
MBTransQuantInterBVOP(const MBParam * pParam,
				  FRAMEINFO * frame,
				  MACROBLOCK * pMB,
				  const uint32_t x_pos,
				  const uint32_t y_pos,
				  int16_t data[6 * 64],
				  int16_t qcoeff[6 * 64])
{
	uint8_t cbp;
	
/* there is no MBTrans for Inter block, that's done in motion compensation already */

	MBfDCT(pParam,frame,pMB,data);
	cbp = MBQuantInter(pParam,frame->quant,data,qcoeff);

	/*
	 * History comment:
	 * we don't have to DeQuant, iDCT and Transfer back data for B-frames
	 */

	/* 
	 * As an exception to the previous rule, if we are willing to have extra
	 * stats then we have to DeQuant, iDCT and Transfer back the data :-)
	 */
	if(frame->vop_flags & XVID_EXTRASTATS) {
		MBDeQuantInter(pParam,frame->quant,data,qcoeff,cbp);
		MBiDCT(data,cbp);
		MBTransAdd(pParam,frame,pMB,x_pos,y_pos,data,cbp);
	}

	return cbp;
}


void
MBfDCT(const MBParam * pParam,
				  FRAMEINFO * frame,
				  MACROBLOCK * pMB,
				  int16_t data[6 * 64])
{	
	int i;

	start_timer();
	pMB->field_dct = 0;
	if ((frame->vol_flags & XVID_INTERLACING)) {
		pMB->field_dct = MBDecideFieldDCT(data);
	}
	stop_interlacing_timer();

	for (i = 0; i < 6; i++) {
		start_timer();
		fdct(&data[i * 64]);
		stop_dct_timer();
	}
}

void
MBQuantDeQuantIntra(const MBParam * pParam,
				  	FRAMEINFO * frame,
				  	MACROBLOCK * pMB,
				  	int16_t qcoeff[6 * 64],
  				  	int16_t data[6*64])
{
	int i;
	int iQuant = frame->quant;

	start_timer();
	pMB->field_dct = 0;
	if ((frame->vol_flags & XVID_INTERLACING)) {
		pMB->field_dct = MBDecideFieldDCT(data);
	}
	stop_interlacing_timer();

	for (i = 0; i < 6; i++) {
		uint32_t iDcScaler = get_dc_scaler(iQuant, i < 4);

		if (!(pParam->vol_flags & XVID_MPEGQUANT)) {
			start_timer();
			quant_intra(&qcoeff[i * 64], &data[i * 64], iQuant, iDcScaler);
			stop_quant_timer();

			start_timer();
			dequant_intra(&data[i * 64], &qcoeff[i * 64], iQuant, iDcScaler);
			stop_iquant_timer();
		} else {
			start_timer();
			quant4_intra(&qcoeff[i * 64], &data[i * 64], iQuant, iDcScaler);
			stop_quant_timer();

			start_timer();
			dequant4_intra(&data[i * 64], &qcoeff[i * 64], iQuant, iDcScaler);
			stop_iquant_timer();
		}
	}
}

void
MBQuantIntra(const MBParam * pParam,
		  	 FRAMEINFO * frame,
			 MACROBLOCK *pMB,
		     int16_t qcoeff[6 * 64],
			 int16_t data[6*64])
{
	int i;
	int iQuant = frame->quant;

	start_timer();
	pMB->field_dct = 0;
	if ((frame->vol_flags & XVID_INTERLACING)) {
		pMB->field_dct = MBDecideFieldDCT(data);
	}
	stop_interlacing_timer();

	for (i = 0; i < 6; i++) {
		uint32_t iDcScaler = get_dc_scaler(iQuant, i < 4);

		if (!(pParam->vol_flags & XVID_MPEGQUANT)) {
			start_timer();
			quant_intra(&qcoeff[i * 64], &data[i * 64], iQuant, iDcScaler);
			stop_quant_timer();
		} else {
			start_timer();
			quant4_intra(&qcoeff[i * 64], &data[i * 64], iQuant, iDcScaler);
			stop_quant_timer();
		}
	}
}

void
MBDeQuantIntra(const MBParam * pParam,
			   const int iQuant,
				  int16_t qcoeff[6 * 64],
				  int16_t data[6*64])
{
	int i;

	for (i = 0; i < 6; i++) {
		uint32_t iDcScaler = get_dc_scaler(iQuant, i < 4);

		if (!(pParam->vol_flags & XVID_MPEGQUANT)) {
			start_timer();
			dequant_intra(&data[i * 64], &qcoeff[i * 64], iQuant, iDcScaler);
			stop_iquant_timer();
		} else {
			start_timer();
			dequant4_intra(&data[i * 64], &qcoeff[i * 64], iQuant, iDcScaler);
			stop_iquant_timer();
		}
	}
}

uint8_t
MBQuantInter(const MBParam * pParam,
			 const int iQuant,
				  int16_t data[6 * 64],
				  int16_t qcoeff[6 * 64])
{

	int i;
	uint8_t cbp = 0;
	int sum;

	for (i = 0; i < 6; i++) {
	
		if (!(pParam->vol_flags & XVID_MPEGQUANT)) {
			start_timer();
			sum = quant_inter(&qcoeff[i * 64], &data[i * 64], iQuant);
			stop_quant_timer();
		} else {
			start_timer();
			sum = quant4_inter(&qcoeff[i * 64], &data[i * 64], iQuant);
			stop_quant_timer();
		}

		if (sum >= TOOSMALL_LIMIT) {	// skip block ?
			cbp |= 1 << (5 - i);
		}
	}
	return cbp;
}

void 
MBDeQuantInter(	const MBParam * pParam,
				const int iQuant,
				  int16_t data[6 * 64],
				  int16_t qcoeff[6 * 64],
				  const uint8_t cbp)
{
	int i;

	for (i = 0; i < 6; i++) {
		if (cbp & (1 << (5 - i)))
		{	
			if (!(pParam->vol_flags & XVID_MPEGQUANT)) {
				start_timer();
				dequant_inter(&data[i * 64], &qcoeff[i * 64], iQuant);
				stop_iquant_timer();
			} else {
				start_timer();
				dequant4_inter(&data[i * 64], &qcoeff[i * 64], iQuant);
				stop_iquant_timer();
			}
		}
	}
}

void
MBiDCT(	int16_t data[6 * 64],
		const uint8_t cbp)
{
	int i;

	for (i = 0; i < 6; i++) {
		if (cbp & (1 << (5 - i)))
		{	
			start_timer();
			idct(&data[i * 64]);
			stop_idct_timer();
		
		}
	}
}


void
MBTrans(const MBParam * pParam,
				  FRAMEINFO * frame,
				  MACROBLOCK * pMB,
				  const uint32_t x_pos,
				  const uint32_t y_pos,
				  int16_t data[6 * 64])
{
	uint32_t stride = pParam->edged_width;
	uint32_t stride2 = stride / 2;
	uint32_t next_block = stride * 8;
	uint8_t *pY_Cur, *pU_Cur, *pV_Cur;
	IMAGE *pCurrent = &frame->image;

	pY_Cur = pCurrent->y + (y_pos << 4) * stride + (x_pos << 4);
	pU_Cur = pCurrent->u + (y_pos << 3) * stride2 + (x_pos << 3);
	pV_Cur = pCurrent->v + (y_pos << 3) * stride2 + (x_pos << 3);

	start_timer();
	transfer_8to16copy(&data[0 * 64], pY_Cur, stride);
	transfer_8to16copy(&data[1 * 64], pY_Cur + 8, stride);
	transfer_8to16copy(&data[2 * 64], pY_Cur + next_block, stride);
	transfer_8to16copy(&data[3 * 64], pY_Cur + next_block + 8, stride);
	transfer_8to16copy(&data[4 * 64], pU_Cur, stride2);
	transfer_8to16copy(&data[5 * 64], pV_Cur, stride2);
	stop_transfer_timer();
}
	
void
MBTransAdd(const MBParam * pParam,
				  FRAMEINFO * frame,
				  MACROBLOCK * pMB,
				  const uint32_t x_pos,
				  const uint32_t y_pos,
				  int16_t data[6 * 64],
				  const uint8_t cbp)
{
	uint8_t *pY_Cur, *pU_Cur, *pV_Cur;
	uint32_t stride = pParam->edged_width;
	uint32_t stride2 = stride / 2;
	uint32_t next_block = stride * 8;
	IMAGE *pCurrent = &frame->image;

	pY_Cur = pCurrent->y + (y_pos << 4) * stride + (x_pos << 4);
	pU_Cur = pCurrent->u + (y_pos << 3) * stride2 + (x_pos << 3);
	pV_Cur = pCurrent->v + (y_pos << 3) * stride2 + (x_pos << 3);

	if (pMB->field_dct) {
		next_block = stride;
		stride *= 2;
	}

	start_timer();
	if (cbp & 32)
		transfer_16to8add(pY_Cur, &data[0 * 64], stride);
	if (cbp & 16)
		transfer_16to8add(pY_Cur + 8, &data[1 * 64], stride);
	if (cbp & 8)
		transfer_16to8add(pY_Cur + next_block, &data[2 * 64], stride);
	if (cbp & 4)
		transfer_16to8add(pY_Cur + next_block + 8, &data[3 * 64], stride);
	if (cbp & 2)
		transfer_16to8add(pU_Cur, &data[4 * 64], stride2);
	if (cbp & 1)
		transfer_16to8add(pV_Cur, &data[5 * 64], stride2);
	stop_transfer_timer();
}



/* permute block and return field dct choice */


uint32_t
MBDecideFieldDCT(int16_t data[6 * 64])
{
	uint32_t field = MBFieldTest(data);

	if (field) {
		MBFrameToField(data);
	}

	return field;
}


/* if sum(diff between field lines) < sum(diff between frame lines), use field dct */

uint32_t
MBFieldTest_c(int16_t data[6 * 64])
{
	const uint8_t blocks[] =
		{ 0 * 64, 0 * 64, 0 * 64, 0 * 64, 2 * 64, 2 * 64, 2 * 64, 2 * 64 };
	const uint8_t lines[] = { 0, 16, 32, 48, 0, 16, 32, 48 };

	int frame = 0, field = 0;
	int i, j;

	for (i = 0; i < 7; ++i) {
		for (j = 0; j < 8; ++j) {
			frame +=
				ABS(data[0 * 64 + (i + 1) * 8 + j] - data[0 * 64 + i * 8 + j]);
			frame +=
				ABS(data[1 * 64 + (i + 1) * 8 + j] - data[1 * 64 + i * 8 + j]);
			frame +=
				ABS(data[2 * 64 + (i + 1) * 8 + j] - data[2 * 64 + i * 8 + j]);
			frame +=
				ABS(data[3 * 64 + (i + 1) * 8 + j] - data[3 * 64 + i * 8 + j]);

			field +=
				ABS(data[blocks[i + 1] + lines[i + 1] + j] -
					data[blocks[i] + lines[i] + j]);
			field +=
				ABS(data[blocks[i + 1] + lines[i + 1] + 8 + j] -
					data[blocks[i] + lines[i] + 8 + j]);
			field +=
				ABS(data[blocks[i + 1] + 64 + lines[i + 1] + j] -
					data[blocks[i] + 64 + lines[i] + j]);
			field +=
				ABS(data[blocks[i + 1] + 64 + lines[i + 1] + 8 + j] -
					data[blocks[i] + 64 + lines[i] + 8 + j]);
		}
	}

	return (frame >= (field + 350));
}


/* deinterlace Y blocks vertically */

#define MOVLINE(X,Y) memcpy(X, Y, sizeof(tmp))
#define LINE(X,Y)    &data[X*64 + Y*8]

void
MBFrameToField(int16_t data[6 * 64])
{
	int16_t tmp[8];

	/* left blocks */

	// 1=2, 2=4, 4=8, 8=1
	MOVLINE(tmp, LINE(0, 1));
	MOVLINE(LINE(0, 1), LINE(0, 2));
	MOVLINE(LINE(0, 2), LINE(0, 4));
	MOVLINE(LINE(0, 4), LINE(2, 0));
	MOVLINE(LINE(2, 0), tmp);

	// 3=6, 6=12, 12=9, 9=3
	MOVLINE(tmp, LINE(0, 3));
	MOVLINE(LINE(0, 3), LINE(0, 6));
	MOVLINE(LINE(0, 6), LINE(2, 4));
	MOVLINE(LINE(2, 4), LINE(2, 1));
	MOVLINE(LINE(2, 1), tmp);

	// 5=10, 10=5
	MOVLINE(tmp, LINE(0, 5));
	MOVLINE(LINE(0, 5), LINE(2, 2));
	MOVLINE(LINE(2, 2), tmp);

	// 7=14, 14=13, 13=11, 11=7
	MOVLINE(tmp, LINE(0, 7));
	MOVLINE(LINE(0, 7), LINE(2, 6));
	MOVLINE(LINE(2, 6), LINE(2, 5));
	MOVLINE(LINE(2, 5), LINE(2, 3));
	MOVLINE(LINE(2, 3), tmp);

	/* right blocks */

	// 1=2, 2=4, 4=8, 8=1
	MOVLINE(tmp, LINE(1, 1));
	MOVLINE(LINE(1, 1), LINE(1, 2));
	MOVLINE(LINE(1, 2), LINE(1, 4));
	MOVLINE(LINE(1, 4), LINE(3, 0));
	MOVLINE(LINE(3, 0), tmp);

	// 3=6, 6=12, 12=9, 9=3
	MOVLINE(tmp, LINE(1, 3));
	MOVLINE(LINE(1, 3), LINE(1, 6));
	MOVLINE(LINE(1, 6), LINE(3, 4));
	MOVLINE(LINE(3, 4), LINE(3, 1));
	MOVLINE(LINE(3, 1), tmp);

	// 5=10, 10=5
	MOVLINE(tmp, LINE(1, 5));
	MOVLINE(LINE(1, 5), LINE(3, 2));
	MOVLINE(LINE(3, 2), tmp);

	// 7=14, 14=13, 13=11, 11=7
	MOVLINE(tmp, LINE(1, 7));
	MOVLINE(LINE(1, 7), LINE(3, 6));
	MOVLINE(LINE(3, 6), LINE(3, 5));
	MOVLINE(LINE(3, 5), LINE(3, 3));
	MOVLINE(LINE(3, 3), tmp);
}

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