⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mbtransquant.c

📁 基于Linux的ffmepg decoder
💻 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 + -