📄 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.29 2005/11/22 10:23:01 suxen_drol 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_tMBDecideFieldDCT(int16_t data[6 * 64]){ uint32_t field = MBFieldTest(data); if (field) MBFrameToField(data); return field;}/* Performs Forward DCT on all blocks */static __inline voidMBfDCT(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 voidMBiDCT(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 voidMBQuantIntra(const MBParam * pParam, const FRAMEINFO * const frame, const MACROBLOCK * pMB, int16_t qcoeff[6 * 64], int16_t data[6*64]){ int mpeg; int scaler_lum, scaler_chr; quant_intraFuncPtr const quant[2] = { quant_h263_intra, quant_mpeg_intra }; mpeg = !!(pParam->vol_flags & XVID_VOL_MPEGQUANT); scaler_lum = get_dc_scaler(pMB->quant, 1); scaler_chr = get_dc_scaler(pMB->quant, 0); /* Quantize the block */ start_timer(); quant[mpeg](&data[0 * 64], &qcoeff[0 * 64], pMB->quant, scaler_lum, pParam->mpeg_quant_matrices); quant[mpeg](&data[1 * 64], &qcoeff[1 * 64], pMB->quant, scaler_lum, pParam->mpeg_quant_matrices); quant[mpeg](&data[2 * 64], &qcoeff[2 * 64], pMB->quant, scaler_lum, pParam->mpeg_quant_matrices); quant[mpeg](&data[3 * 64], &qcoeff[3 * 64], pMB->quant, scaler_lum, pParam->mpeg_quant_matrices); quant[mpeg](&data[4 * 64], &qcoeff[4 * 64], pMB->quant, scaler_chr, pParam->mpeg_quant_matrices); quant[mpeg](&data[5 * 64], &qcoeff[5 * 64], pMB->quant, scaler_chr, pParam->mpeg_quant_matrices); stop_quant_timer();}/* DeQuantize all blocks -- Intra mode */static __inline voidMBDeQuantIntra(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 intdct_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);/* Quantize all blocks -- Inter mode */static __inline uint8_tMBQuantInter(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); } 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 voidMBDeQuantInter(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 voidMBTrans8to16(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 voidMBTrans16to8(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 ****************************************************************************/voidMBTransQuantIntra(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_tMBTransQuantInter(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); if (frame->vop_flags & XVID_VOP_CARTOON)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -