📄 mbtransquant.c
字号:
#include "portab.h"
#include "ftmcp100.h"
#include "global.h"
#include "quant_h263.h"
#include "encoder.h"
#include "mem_transfer.h"
#include "zigzag.h"
#define SCALEBITS 17
#define FIX(X) ((1L << SCALEBITS) / (X) + 1)
#define MIN(X, Y) ((X)<(Y)?(X):(Y))
#define MAX(X, Y) ((X)>(Y)?(X):(Y))
#define VM18P 3
#define VM18Q 4
const uint32_t multipliers[32] = {
0, FIX(2), FIX(4), FIX(6),
FIX(8), FIX(10), FIX(12), FIX(14),
FIX(16), FIX(18), FIX(20), FIX(22),
FIX(24), FIX(26), FIX(28), FIX(30),
FIX(32), FIX(34), FIX(36), FIX(38),
FIX(40), FIX(42), FIX(44), FIX(46),
FIX(48), FIX(50), FIX(52), FIX(54),
FIX(56), FIX(58), FIX(60), FIX(62)
};
const uint16_t div_array[48] = {
1, 1, 1, 43691, 32768, 26215, 21846, 18725, 16384, 14564,
13108, 11916, 10923, 10083, 9363, 8739, 8192, 7711, 7282, 6899,
6554, 6242, 5958, 5699, 5462, 5243, 5042, 4855, 4682, 4520,
4370, 4229, 4096, 3972, 3856, 3745, 3641, 3543, 3450, 3361,
3277, 3197, 3121, 3048, 2979, 2913, 2850, 2789};
uint32_t
MBTransQuantInter(const MBParam * pParam,
FRAMEINFO * frame,FTMCP100_CODEC *pCodec)
{
uint32_t iQuant = frame->quant;
int32_t index;
DECLARE_MP4_PTR
index = 1 | (pParam->h263 << 14); // H.263 Q, AC don't care, INTER
if (pParam->m_quant_type == MPEG4_QUANT) {
index |= 1 << 3; // MPEG Q, AC don't care, INTER
}
SET_QCR_0(iQuant<<18)
#ifdef CORE_VERSION_1
SET_MCIADDR(INTER_Y0 + (pCodec->even_odd_1 ^ 1) * stride_MB) /// set MC Interpolation and Result Block Start Address Register
#elif defined(CORE_VERSION_2)
SET_MCIADDR(INTER_Y0 + ((pCodec->triple_buffer_selector+2)%3)*stride_MB) // set MC Interpolation and Result Block Start Address Register
#endif
return index;
}
void
MBTransQuantIntra(const MBParam * pParam,
FRAMEINFO * frame,
MACROBLOCK * pMB_mc,
const uint32_t x_pos,
const uint32_t y_pos,
uint32_t mb_width,FTMCP100_CODEC *pCodec)
{
#if defined(CORE_VERSION_2)
uint32_t iQuant = pMB_mc->quant;
int32_t index;
volatile MDMA *pmdma = MDMA1;
unsigned int *pDMA;
int last_MB=0;
unsigned int cpsts;
DECLARE_MP4_PTR
POLL_MARKER1_START
// the index variable is used to set the MCCTL register, their corresponding setting is as shown below :
// REMAP INTRA and MC_GO SVH (short header) MP4M(MPEG4 mode of current block) ACDC_PARM INTRA_FRAME
index = ((pCodec->even_odd_I)<<4) | 3 | (pParam->h263 << 14) | (MODE_INTRA) << 6 | pCodec->acdc_status << 11 | 1 << 15;
// H.263 Q, AC enable, INTRA
if (pParam->m_quant_type == MPEG4_QUANT) {
index |= 1 << 3; // MPEG Q, AC enable, INTRA
}
// set the Quantization Coefficient Register to the specified quantization level.
// QCR_0 register is at 0x1002c , the value of quantization level can be 1 ~ 31
SET_QCR_0(iQuant<<18)
// set the MC Interpolation and Result Block Start Address.
// MCIADDR is at 0x10058
SET_MCIADDR((pCodec->even_odd_1) ? INTER_Y1 : INTER_Y0)
// set the MC Current Block Start Address.
// MCCADDR register is at 0x10020
SET_MCCADDR((pCodec->even_odd_1)? CUR_Y1 : CUR_Y0)
POLL_MARKER1_END
// here, we are waiting for the end of DMA transfer for predictor
POLL_MARKER_S
while((pmdma->Status & 0x1) == 0) {}
POLL_MARKER_E
// well, from the RTL simulation waveform, the VLC done may happen later than MC done,
// so we should check here before MC can go
// check whether the VLC is done or not
// CPSTS register is at address 0x10028
do {
READ_CPSTS(cpsts)
} while (!(cpsts&0x08000));
// set the MC Control Register and begin MC engine
// MCCTL register is at 0x1001C
SET_MCCTL(index)
// From the waveform of RTL simulation , you can see that the time spend in
// MC engine is quite long, so we can stuff more codes here between MC go and MC done
pCodec->even_odd_1 ^= 1;
pDMA=pCodec->DMA_COMMAND_local+pCodec->even_odd_1*DMA_COMMAND_QUEUE_STRIDE;
pDMA[23]=0x04A00010; // for old code compatibility
// make it group 2, to sync to MC done
pDMA[39]=0x04A42010; // load predictor
pDMA[43]=0x00942010; // store predictor
if(x_pos==0 && y_pos==0) // the very first time
{
// make it group 1, to disable these commands
pDMA[27]=0x04B01040;
pDMA[31]=0x04B01010;
pDMA[35]=0x04B01010;
}
else // not the very first time
{
// enable these commands again
pDMA[27]=0x04B00040;
pDMA[31]=0x04B00010;
pDMA[35]=0x04B00010;
}
pMB_mc->mode = MODE_INTRA;
if(pParam->enable_4mv)
{
pMB_mc->mv16x_0 = 0;
pMB_mc->mv16y_0 = 0;
pMB_mc->mv16x_1 = 0;
pMB_mc->mv16y_1 = 0;
pMB_mc->mv16x_2 = 0;
pMB_mc->mv16y_2 = 0;
}
pMB_mc->mv16x_3 = 0;
pMB_mc->mv16y_3 = 0;
pCodec->even_odd_I ^= 1;
if (pParam->resyn==0)
{
pCodec->acdc_status = 0; // make none default predictor
}
if ((y_pos==0) & (x_pos!=(pParam->mb_width-1)))
{
if (pParam->resyn==0)
{
pCodec->acdc_status = 6; // make Diagonal and Top default predictor
}
} else if (x_pos==(pParam->mb_width-1)) {
pDMA[36] = (uint32_t) pCodec->pred_value_phy;
} else
pDMA[36] = (uint32_t) (pCodec->pred_value_phy + (x_pos+1) * 32);
pDMA[40] = (uint32_t) (pCodec->pred_value_phy + x_pos * 32);
pDMA[37] = TRANSLATE_LOCAL_MEMORY_BASE_ADDRESS(LOCAL_PREDICTOR0 + (pCodec->even_odd_I)*0x80);
// start to DMA move (from 12th to 12+32-1=43th)
// to the system memory and start DMA procedure..
// it will fetch next macroblock in current image to the local memory selected by 'even_odd_1' flag
DMA_MOVE(12+pCodec->even_odd_1*DMA_COMMAND_QUEUE_STRIDE, 0x4B00020)
if((x_pos==(pParam->mb_width-1)) && (y_pos==(pParam->mb_height-1)) )
{
unsigned int *pDMA2=pCodec->DMA_COMMAND_local+(pCodec->even_odd_1^1)*DMA_COMMAND_QUEUE_STRIDE;
last_MB=1;
pDMA2[35]=0x00900010;
}
// check whether the MC is done or not by reading the Coprocessor Status Register
POLL_MC_DONE_MARKER_START
do {
READ_CPSTS(index)
} while(!(index&0x02));
POLL_MC_DONE_MARKER_END
if(last_MB)
{ // if it is the last MB, we need to transfer the last reconstrcuted data to reconstructed image system buffer
POLL_MARKER_S
while((pmdma->Status & 0x1) == 0) {}
POLL_MARKER_E
DMA_MOVE(24+(pCodec->even_odd_1^1)*DMA_COMMAND_QUEUE_STRIDE, 0x4B0000C)
}
#elif defined(CORE_VERSION_1)
uint32_t iQuant = pMB_mc->quant;
int32_t index;
volatile MDMA *pmdma = MDMA1;
DECLARE_MP4_PTR
// the index variable is used to set the MCCTL register, their corresponding setting is as shown below :
// REMAP INTRA and MC_GO SVH (short header) MP4M(MPEG4 mode of current block) ACDC_PARM INTRA_FRAME
index = ((pCodec->even_odd_I)<<4) | 3 | (pParam->h263 << 14) | (MODE_INTRA) << 6 | pCodec->acdc_status << 11 | 1 << 15;
// H.263 Q, AC enable, INTRA
if (pParam->m_quant_type == MPEG4_QUANT) {
index |= 1 << 3; // MPEG Q, AC enable, INTRA
}
// set the Quantization Coefficient Register to the specified quantization level.
// QCR_0 register is at 0x1002c , the value of quantization level can be 1 ~ 31
SET_QCR_0(iQuant<<18)
// set the MC Interpolation and Result Block Start Address.
// MCIADDR is at 0x10058
SET_MCIADDR(INTER_Y0 + (pCodec->even_odd_1) * stride_MB)
// set the MC Current Block Start Address.
// MCCADDR register is at 0x10020
SET_MCCADDR(CUR_Y0 + (pCodec->even_odd_1) * stride_MB)
POLL_MARKER_S
while((pmdma->Status & 0x1) == 0) {}
POLL_MARKER_E
// set the MC Control Register and begin MC engine
// MCCTL register is at 0x1001C
SET_MCCTL(index)
pCodec->even_odd_1 ^= 1;
// prepare to load next macroblock by DMA
// choose next yuv buffer in local memory by changing next buffer's local memory address
index = pCodec->DMA_COMMAND_local[13] = (uint32_t) CUR_Y0 + (pCodec->even_odd_1) * stride_MB;
index = pCodec->DMA_COMMAND_local[17] = index + 256;
pCodec->DMA_COMMAND_local[21] = index + 64;
// let's prepare to move the yuv data in reconstructed buffer
// to original current cur->image.y cur->image.u and cur->image.v
// so the reconstructed buffer data will destroy the original yuv buffer
// but for wellsyn platform, we need move the reconstrcuted data to another
// real reconstructed buffer instead of original .yuv image buffer.
pCodec->DMA_COMMAND_local[28] += 256;
pCodec->DMA_COMMAND_local[32] += 64;
pCodec->DMA_COMMAND_local[36] += 64;
// prepare the DMA to fetch next macroblock in current image
// to the local memory
pCodec->DMA_COMMAND_local[12] = pCodec->DMA_COMMAND_local[12] + 16*16;
pCodec->DMA_COMMAND_local[16] = pCodec->DMA_COMMAND_local[16] + 8*8;
pCodec->DMA_COMMAND_local[20] = pCodec->DMA_COMMAND_local[20] + 8*8;
// OK, move the local DMA commands (from 12th to 12+12-1=23th)
// to the system memory and start DMA procedure..
// it will fetch next macroblock in current image to the local memory selected by 'even_odd_1' flag
DMA_MOVE(12, 0x4B0000C)
pMB_mc->mode = MODE_INTRA;
if(pParam->enable_4mv)
{
pMB_mc->mv16x_0 = 0;
pMB_mc->mv16y_0 = 0;
pMB_mc->mv16x_1 = 0;
pMB_mc->mv16y_1 = 0;
pMB_mc->mv16x_2 = 0;
pMB_mc->mv16y_2 = 0;
}
pMB_mc->mv16x_3 = 0;
pMB_mc->mv16y_3 = 0;
pCodec->even_odd_I ^= 1;
if (pParam->resyn==0)
{
pCodec->acdc_status = 0; // make none default predictor
}
if ((y_pos==0) & (x_pos!=(pParam->mb_width-1)))
{
if (pParam->resyn==0)
{
pCodec->acdc_status = 6; // make Diagonal and Top default predictor
}
} else if (x_pos==(pParam->mb_width-1)) {
pCodec->DMA_COMMAND_local[24] = (uint32_t) pCodec->pred_value_phy;
} else
pCodec->DMA_COMMAND_local[24] = (uint32_t) (pCodec->pred_value_phy + (x_pos+1) * 32);
pCodec->DMA_COMMAND_local[40] = (uint32_t) (pCodec->pred_value_phy + x_pos * 32);
pCodec->DMA_COMMAND_local[25] = (uint32_t) LOCAL_PREDICTOR0 + (pCodec->even_odd_I)*0x80;
// we need to set the source local memory address of reconstructed
// buffer for DMA operation in order to move the reconstructed buffer to original
// current cur->image.y cur->image.u and cur->image.v
index = pCodec->DMA_COMMAND_local[29] = (uint32_t) INTER_Y0 + (pCodec->even_odd_1^1) * stride_MB;
index = pCodec->DMA_COMMAND_local[33] = index + 256;
pCodec->DMA_COMMAND_local[37] = index + 64;
// check whether the MC is done or not by reading the Coprocessor Status Register
POLL_MC_DONE_MARKER_START
do {
READ_CPSTS(index)
} while(!(index&0x02));
POLL_MC_DONE_MARKER_END
POLL_MARKER_S
// check whether the fetch of next macroblock in current image to the local memory is done or not
while((pmdma->Status & 0x1) == 0) {}
POLL_MARKER_E
/* store ref YUV */
/* store cur predictor */
// OK, move the local DMA commands (from 24th to 24+20(0x14)-1=43th)
// to the system memory and start DMA procedure..
// It will begin to move the reconstructed yuv data in reconstructed buffer
// to the original current cur->image.y cur->image.u and cur->image.v buffer
// so the reconstructed buffer data will destroy the original yuv buffer
// also, it will store the current predictor...
DMA_MOVE(24, 0x4B00014)
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -