📄 mbtransquant.c
字号:
/*****************************************************************************
*
* XVID MPEG-4 VIDEO CODEC
* - MB Transfert/Quantization functions -
*
* Copyright(C) 2001-2003 Peter Ross <pross@xvid.org>
* 2001-2003 Michael Militzer <isibaar@xvid.org>
* 2003 Edouard Gomez <ed.gomez@free.fr>
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: mbtransquant.c,v 1.32 2006/07/10 08:09:59 syskin Exp $
*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../portab.h"
#include "mbfunctions.h"
#include "../global.h"
#include "mem_transfer.h"
#include "timer.h"
#include "../bitstream/mbcoding.h"
#include "../bitstream/zigzag.h"
#include "../dct/fdct.h"
#include "../dct/idct.h"
#include "../quant/quant.h"
#include "../encoder.h"
#include "../quant/quant_matrix.h"
MBFIELDTEST_PTR MBFieldTest;
/*
* Skip blocks having a coefficient sum below this value. This value will be
* corrected according to the MB quantizer to avoid artifacts for quant==1
*/
#define PVOP_TOOSMALL_LIMIT 1
#define BVOP_TOOSMALL_LIMIT 3
/*****************************************************************************
* Local functions
****************************************************************************/
/* permute block and return field dct choice */
static __inline uint32_t
MBDecideFieldDCT(int16_t data[6 * 64])
{
uint32_t field = MBFieldTest(data);
if (field)
MBFrameToField(data);
return field;
}
/* Performs Forward DCT on all blocks */
static __inline void
MBfDCT(const MBParam * const pParam,
const FRAMEINFO * const frame,
MACROBLOCK * const pMB,
uint32_t x_pos,
uint32_t y_pos,
int16_t data[6 * 64])
{
/* Handles interlacing */
start_timer();
pMB->field_dct = 0;
if ((frame->vol_flags & XVID_VOL_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();
/* Perform DCT */
start_timer();
fdct((short * const)&data[0 * 64]);
fdct((short * const)&data[1 * 64]);
fdct((short * const)&data[2 * 64]);
fdct((short * const)&data[3 * 64]);
fdct((short * const)&data[4 * 64]);
fdct((short * const)&data[5 * 64]);
stop_dct_timer();
}
/* Performs Inverse DCT on all blocks */
static __inline void
MBiDCT(int16_t data[6 * 64],
const uint8_t cbp)
{
start_timer();
if(cbp & (1 << (5 - 0))) idct((short * const)&data[0 * 64]);
if(cbp & (1 << (5 - 1))) idct((short * const)&data[1 * 64]);
if(cbp & (1 << (5 - 2))) idct((short * const)&data[2 * 64]);
if(cbp & (1 << (5 - 3))) idct((short * const)&data[3 * 64]);
if(cbp & (1 << (5 - 4))) idct((short * const)&data[4 * 64]);
if(cbp & (1 << (5 - 5))) idct((short * const)&data[5 * 64]);
stop_idct_timer();
}
/* Quantize all blocks -- Intra mode */
static __inline void
MBQuantIntra(const MBParam * pParam,
const FRAMEINFO * const frame,
const MACROBLOCK * pMB,
int16_t qcoeff[6 * 64],
int16_t data[6*64])
{
int scaler_lum, scaler_chr;
quant_intraFuncPtr quant;
/* check if quant matrices need to be re-initialized with new quant */
if (pParam->vol_flags & XVID_VOL_MPEGQUANT) {
if (pParam->last_quant_initialized_intra != pMB->quant) {
init_intra_matrix(pParam->mpeg_quant_matrices, pMB->quant);
}
quant = quant_mpeg_intra;
} else {
quant = quant_h263_intra;
}
scaler_lum = get_dc_scaler(pMB->quant, 1);
scaler_chr = get_dc_scaler(pMB->quant, 0);
/* Quantize the block */
start_timer();
quant(&data[0 * 64], &qcoeff[0 * 64], pMB->quant, scaler_lum, pParam->mpeg_quant_matrices);
quant(&data[1 * 64], &qcoeff[1 * 64], pMB->quant, scaler_lum, pParam->mpeg_quant_matrices);
quant(&data[2 * 64], &qcoeff[2 * 64], pMB->quant, scaler_lum, pParam->mpeg_quant_matrices);
quant(&data[3 * 64], &qcoeff[3 * 64], pMB->quant, scaler_lum, pParam->mpeg_quant_matrices);
quant(&data[4 * 64], &qcoeff[4 * 64], pMB->quant, scaler_chr, pParam->mpeg_quant_matrices);
quant(&data[5 * 64], &qcoeff[5 * 64], pMB->quant, scaler_chr, pParam->mpeg_quant_matrices);
stop_quant_timer();
}
/* DeQuantize all blocks -- Intra mode */
static __inline void
MBDeQuantIntra(const MBParam * pParam,
const int iQuant,
int16_t qcoeff[6 * 64],
int16_t data[6*64])
{
int mpeg;
int scaler_lum, scaler_chr;
quant_intraFuncPtr const dequant[2] =
{
dequant_h263_intra,
dequant_mpeg_intra
};
mpeg = !!(pParam->vol_flags & XVID_VOL_MPEGQUANT);
scaler_lum = get_dc_scaler(iQuant, 1);
scaler_chr = get_dc_scaler(iQuant, 0);
start_timer();
dequant[mpeg](&qcoeff[0 * 64], &data[0 * 64], iQuant, scaler_lum, pParam->mpeg_quant_matrices);
dequant[mpeg](&qcoeff[1 * 64], &data[1 * 64], iQuant, scaler_lum, pParam->mpeg_quant_matrices);
dequant[mpeg](&qcoeff[2 * 64], &data[2 * 64], iQuant, scaler_lum, pParam->mpeg_quant_matrices);
dequant[mpeg](&qcoeff[3 * 64], &data[3 * 64], iQuant, scaler_lum, pParam->mpeg_quant_matrices);
dequant[mpeg](&qcoeff[4 * 64], &data[4 * 64], iQuant, scaler_chr, pParam->mpeg_quant_matrices);
dequant[mpeg](&qcoeff[5 * 64], &data[5 * 64], iQuant, scaler_chr, pParam->mpeg_quant_matrices);
stop_iquant_timer();
}
static int
dct_quantize_trellis_c(int16_t *const Out,
const int16_t *const In,
int Q,
const uint16_t * const Zigzag,
const uint16_t * const QuantMatrix,
int Non_Zero,
int Sum,
int Lambda_Mod);
/* Quantize all blocks -- Inter mode */
static __inline uint8_t
MBQuantInter(const MBParam * pParam,
const FRAMEINFO * const frame,
const MACROBLOCK * pMB,
int16_t data[6 * 64],
int16_t qcoeff[6 * 64],
int bvop,
int limit)
{
int i;
uint8_t cbp = 0;
int sum;
int code_block, mpeg;
quant_interFuncPtr const quant[2] =
{
quant_h263_inter,
quant_mpeg_inter
};
mpeg = !!(pParam->vol_flags & XVID_VOL_MPEGQUANT);
for (i = 0; i < 6; i++) {
/* Quantize the block */
start_timer();
sum = quant[mpeg](&qcoeff[i*64], &data[i*64], pMB->quant, pParam->mpeg_quant_matrices);
if(sum && (pMB->quant > 2) && (frame->vop_flags & XVID_VOP_TRELLISQUANT)) {
const uint16_t *matrix;
const static uint16_t h263matrix[] =
{
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16
};
matrix = (mpeg)?get_inter_matrix(pParam->mpeg_quant_matrices):h263matrix;
sum = dct_quantize_trellis_c(&qcoeff[i*64], &data[i*64],
pMB->quant, &scan_tables[0][0],
matrix,
63,
sum,
pMB->lambda[i]);
}
stop_quant_timer();
/*
* We code the block if the sum is higher than the limit and if the first
* two AC coefficients in zig zag order are not zero.
*/
code_block = 0;
if ((sum >= limit) || (qcoeff[i*64+1] != 0) || (qcoeff[i*64+8] != 0)) {
code_block = 1;
} else {
if (bvop && (pMB->mode == MODE_DIRECT || pMB->mode == MODE_DIRECT_NO4V)) {
/* dark blocks prevention for direct mode */
if ((qcoeff[i*64] < -1) || (qcoeff[i*64] > 0))
code_block = 1;
} else {
/* not direct mode */
if (qcoeff[i*64] != 0)
code_block = 1;
}
}
/* Set the corresponding cbp bit */
cbp |= code_block << (5 - i);
}
return(cbp);
}
/* DeQuantize all blocks -- Inter mode */
static __inline void
MBDeQuantInter(const MBParam * pParam,
const int iQuant,
int16_t data[6 * 64],
int16_t qcoeff[6 * 64],
const uint8_t cbp)
{
int mpeg;
quant_interFuncPtr const dequant[2] =
{
dequant_h263_inter,
dequant_mpeg_inter
};
mpeg = !!(pParam->vol_flags & XVID_VOL_MPEGQUANT);
start_timer();
if(cbp & (1 << (5 - 0))) dequant[mpeg](&data[0 * 64], &qcoeff[0 * 64], iQuant, pParam->mpeg_quant_matrices);
if(cbp & (1 << (5 - 1))) dequant[mpeg](&data[1 * 64], &qcoeff[1 * 64], iQuant, pParam->mpeg_quant_matrices);
if(cbp & (1 << (5 - 2))) dequant[mpeg](&data[2 * 64], &qcoeff[2 * 64], iQuant, pParam->mpeg_quant_matrices);
if(cbp & (1 << (5 - 3))) dequant[mpeg](&data[3 * 64], &qcoeff[3 * 64], iQuant, pParam->mpeg_quant_matrices);
if(cbp & (1 << (5 - 4))) dequant[mpeg](&data[4 * 64], &qcoeff[4 * 64], iQuant, pParam->mpeg_quant_matrices);
if(cbp & (1 << (5 - 5))) dequant[mpeg](&data[5 * 64], &qcoeff[5 * 64], iQuant, pParam->mpeg_quant_matrices);
stop_iquant_timer();
}
typedef void (transfer_operation_8to16_t) (int16_t *Dst, const uint8_t *Src, int BpS);
typedef void (transfer_operation_16to8_t) (uint8_t *Dst, const int16_t *Src, int BpS);
static __inline void
MBTrans8to16(const MBParam * const pParam,
const FRAMEINFO * const frame,
const MACROBLOCK * const 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;
const IMAGE * const pCurrent = &frame->image;
/* Image pointers */
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);
/* Do the transfer */
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();
}
static __inline void
MBTrans16to8(const MBParam * const pParam,
const FRAMEINFO * const frame,
const MACROBLOCK * const pMB,
const uint32_t x_pos,
const uint32_t y_pos,
int16_t data[6 * 64],
const uint32_t add, /* Must be 1 or 0 */
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;
const IMAGE * const pCurrent = &frame->image;
/* Array of function pointers, indexed by [add] */
transfer_operation_16to8_t * const functions[2] =
{
(transfer_operation_16to8_t*)transfer_16to8copy,
(transfer_operation_16to8_t*)transfer_16to8add,
};
transfer_operation_16to8_t *transfer_op = NULL;
/* Image pointers */
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;
}
/* Operation function */
transfer_op = functions[add];
/* Do the operation */
start_timer();
if (cbp&32) transfer_op(pY_Cur, &data[0 * 64], stride);
if (cbp&16) transfer_op(pY_Cur + 8, &data[1 * 64], stride);
if (cbp& 8) transfer_op(pY_Cur + next_block, &data[2 * 64], stride);
if (cbp& 4) transfer_op(pY_Cur + next_block + 8, &data[3 * 64], stride);
if (cbp& 2) transfer_op(pU_Cur, &data[4 * 64], stride2);
if (cbp& 1) transfer_op(pV_Cur, &data[5 * 64], stride2);
stop_transfer_timer();
}
/*****************************************************************************
* Module functions
****************************************************************************/
void
MBTransQuantIntra(const MBParam * const pParam,
const FRAMEINFO * const frame,
MACROBLOCK * const pMB,
const uint32_t x_pos,
const uint32_t y_pos,
int16_t data[6 * 64],
int16_t qcoeff[6 * 64])
{
/* Transfer data */
MBTrans8to16(pParam, frame, pMB, x_pos, y_pos, data);
/* Perform DCT (and field decision) */
MBfDCT(pParam, frame, pMB, x_pos, y_pos, data);
/* Quantize the block */
MBQuantIntra(pParam, frame, pMB, data, qcoeff);
/* DeQuantize the block */
MBDeQuantIntra(pParam, pMB->quant, data, qcoeff);
/* Perform inverse DCT*/
MBiDCT(data, 0x3F);
/* Transfer back the data -- Don't add data */
MBTrans16to8(pParam, frame, pMB, x_pos, y_pos, data, 0, 0x3F);
}
uint8_t
MBTransQuantInter(const MBParam * const pParam,
const FRAMEINFO * const frame,
MACROBLOCK * const pMB,
const uint32_t x_pos,
const uint32_t y_pos,
int16_t data[6 * 64],
int16_t qcoeff[6 * 64])
{
uint8_t cbp;
uint32_t limit;
/* There is no MBTrans8to16 for Inter block, that's done in motion compensation
* already */
/* Perform DCT (and field decision) */
MBfDCT(pParam, frame, pMB, x_pos, y_pos, data);
/* Set the limit threshold */
limit = PVOP_TOOSMALL_LIMIT + ((pMB->quant == 1)? 1 : 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -