📄 mfc_test.c
字号:
INTC_SetVectAddr(NUM_MFC,Isr_Mfc);
INTC_Enable(NUM_MFC);
// 6. Read the golden stream to compare
//--------------------------------------
FAT_GetFileIndex(pGoldenStreamFileName, &selGoldenStream, &oSdhc);
FAT_GetFileSize(selGoldenStream, &nGoldenStreamFileSize, &oSdhc);
Disp("golden stream size = %d bytes\n", nGoldenStreamFileSize);
uGoldenStreamStAddr = uFreeMemBuf;
uFreeMemBuf += nGoldenStreamFileSize;
nReadSize = (nGoldenStreamFileSize < STREAM_BUF_SIZE/2) ? nGoldenStreamFileSize : STREAM_BUF_SIZE/2;
nGoldenStreamOffset = 0;
if (!FAT_ReadFile4(selGoldenStream, nGoldenStreamOffset, (nReadSize+uBlkSz-1)/uBlkSz, uGoldenStreamStAddr, &oSdhc))
Assert(0);
nGoldenStreamOffset += nReadSize;
uSrcFileOffset=0;
uFrameCount=0;
uEncStreamOffset = 0;
bResult = true;
bIsNoMoreStream = (nReadSize == nGoldenStreamFileSize) ? true : false;
while (GetKey() == 0)
{
// 7. Read one Yuv source frame from SD/MMC card
//-----------------------------------------------
if (!FAT_ReadFile6(selSrcYuv, uSrcFileOffset, uSrcYuvFrameSizeInBytes, uSrcYuvBufAddr, &uTrueStAddrOfData, &oSdhc))
break;
uSrcFileOffset += uSrcYuvFrameSizeInBytes;
// 8. Encode one frame
//---------------------
bMfcDone = false;
MFC_SetEncRunOption(false, false);
MFC_SetEncRotEn(false);
MFC_StartEncodingOneFrame(uProcessIdx, uTrueStAddrOfData);
while(bMfcDone != true);
// 9. Compare the encoded stream with the golden one, Load the golden stream if necessary
//----------------------------------------------------------------------------------------
uFrameCount++;
Disp("%d ",uFrameCount);
if (!MFC_IsMoreStreamNeeded(uProcessIdx, nReadSize) && !bIsNoMoreStream)
{
Disp(" more ");
if (!Compare128(uEncBufAddr+(uEncStreamOffset%STREAM_BUF_SIZE),
uGoldenStreamStAddr+(uEncStreamOffset%STREAM_BUF_SIZE), nReadSize/16))
{
bResult = false;
break;
}
uEncStreamOffset += nReadSize;
nReadSize = (nGoldenStreamFileSize-nGoldenStreamOffset < STREAM_BUF_SIZE/2) ?
nGoldenStreamFileSize-nGoldenStreamOffset : STREAM_BUF_SIZE/2;
bIsNoMoreStream = (nReadSize == nGoldenStreamFileSize-nGoldenStreamOffset) ? true : false;
if (!FAT_ReadFile4(selGoldenStream, nGoldenStreamOffset/uBlkSz,
(nReadSize+uBlkSz-1)/uBlkSz, uGoldenStreamStAddr+(nGoldenStreamOffset%STREAM_BUF_SIZE), &oSdhc))
Assert(0);
nGoldenStreamOffset += nReadSize;
MFC_SetRdPtr(uProcessIdx, uEncBufAddr+((nGoldenStreamOffset+STREAM_BUF_SIZE/2)%STREAM_BUF_SIZE));
}
if (uFrameCount >= uNumOfFrames) // end of YUV frame
{
Disp("Encoding ended with %d frames\n", uNumOfFrames);
if (!Compare128(uEncBufAddr+uEncStreamOffset%STREAM_BUF_SIZE,
uGoldenStreamStAddr+uEncStreamOffset%STREAM_BUF_SIZE, nReadSize/16))
{
bResult = false;
}
Disp("Rate control: %.2fkbps\n",
(float)nGoldenStreamFileSize*8/uNumOfFrames*uFrameRate/1000);
break;
}
}
// 10. Report the result of comparison
//-------------------------------------
Disp("\n%s\n\n", bResult ? "Match" : "Mismatch");
FAT_UnloadFileSystem(&oSdhc);
SDHC_CloseMedia(&oSdhc);
MFC_IssueSeqEndCmd(uProcessIdx);
MFC_StopBitProcessor();
}
#endif
//////////
// Function Name : SetEncMode
// Function Description : This function sets encoder mode
// Input : sSel, file number to select
// Output : NONE
// Version :
const char *pEncFile[]=
{
"foreman_qcif_300.yuv",
"mobile_qcif_300.yuv",
"foreman_cif_300.yuv",
"mobile_cif_300.yuv",
"city_vga_300.yuv",
"football_sd601_260.yuv",
"mobile_sd601_260.yuv",
0
};
static void SetEncMode(s32 *sSel)
{
int sEncMode=-1;
#if (USE_SD_STORAGE)
s32 sTmpValue=0;
#else
int sEncFile=-1;
u8 i=0;
#endif
#if USE_SD_STORAGE
Disp("Select the Encoder File : ");
sTmpValue = GetIntNum();
FAT_GetFileName(sTmpValue, pSrcYUVFileName, &oSdhc);
*sSel = sTmpValue;
Disp("Enter the Encoder Width : ");
sTmpValue = GetIntNum();
if(sTmpValue != -1)
{
uEncWidth = sTmpValue;
}
Disp("Enter the Encoder Height : ");
sTmpValue = GetIntNum();
if(sTmpValue != -1)
{
uEncHeight = sTmpValue;
}
Disp("Enter the Encoder Total Frame Number : ");
sTmpValue = GetIntNum();
if(sTmpValue != -1)
{
uEncTotalFrameNum = sTmpValue;
}
#else
do
{
Disp("Select Encoder File: \n");
for(i=0;pEncFile[i]!=0;i++)
{
Disp("[%d] %s\n",i,pEncFile[i]);
}
sEncFile = GetIntNum();
} while(sEncFile == -1);
switch(sEncFile)
{
default:
case 0:
strncpy(pSrcYUVFileName, pEncFile[0], 256);
uEncWidth = 176;
uEncHeight = 144;
uEncTotalFrameNum = 300;
break;
case 1:
strncpy(pSrcYUVFileName, pEncFile[1], 256);
uEncWidth = 176;
uEncHeight = 144;
uEncTotalFrameNum = 300;
break;
case 2:
strncpy(pSrcYUVFileName, pEncFile[2], 256);
uEncWidth = 352;
uEncHeight = 288;
uEncTotalFrameNum = 300;
break;
case 3:
strncpy(pSrcYUVFileName, pEncFile[3], 256);
uEncWidth = 352;
uEncHeight = 288;
uEncTotalFrameNum = 300;
break;
case 4:
strncpy(pSrcYUVFileName, pEncFile[4], 256);
uEncWidth = 640;
uEncHeight = 480;
uEncTotalFrameNum = 300;
break;
case 5:
strncpy(pSrcYUVFileName, pEncFile[5], 256);
uEncWidth = 720;
uEncHeight = 480;
uEncTotalFrameNum = 260;
break;
case 6:
strncpy(pSrcYUVFileName, pEncFile[6], 256);
uEncWidth = 720;
uEncHeight = 480;
uEncTotalFrameNum = 260;
break;
}
#endif
do
{
Disp("Select Encoder mode: \n");
Disp("[0] MPEG4\n");
Disp("[1] H.263\n");
Disp("[2] H.264\n");
sEncMode = GetIntNum();
} while (sEncMode == -1);
eEncMode = (sEncMode == 2) ? AVC_ENC : MP4_ENC;
bIsH263 = (sEncMode == 1) ? true : false;
}
//////////
// Function Name : TestEncoding
// Function Description : This function encodes an YUV file and displays the recon image
// Input : NONE
// Output : NONE
// Version :
static void TestEncoding(void)
{
u32 uFreeMemBuf = MFC_MEMORY_BASE;
u32 uProcessIdx;
u32 uYuvFrameSize;
const char* pEncModeName;
u32 uYuvBufAddr;
s32 sel;
#if (!USE_SD_STORAGE)
u32 uYuvFileAddr, uYuvFileSize;
#endif
u32 uTransferSize;
const int nWriteUnit = STREAM_BUF_SIZE/2;
u32 uStreamOffset = 0;
u32 uSaveBufAddr;
u32 uStreamBufStAddr;
u32 uLcdFbAddr;
CSPACE eLcdBpp;
u32 uLcdWidth, uLcdHeight;
u32 uDecWidth, uDecHeight;
u32 uRecFrmAddrY;
u32 uDispFrameNum;
u32 uFrameCount=0;
u32 uSrcYuvFileOffset = 0;
u32 uWrPtr;
u32 uTrueStAddrOfData;
u32 uRecFrameIdx;
float fEncTime=0;
double fTotEncTime;
#if USE_SD_STORAGE
// 0. Select the YUV file in the SD card.
//-------------------------------------------
while(!SDHC_OpenMedia(SDHC_HCLK, &oSdhc));
if (!FAT_LoadFileSystem(&oSdhc))
Assert(0);
SetEncMode(&sel);
if(sel == -1)
{
Disp("There is the matched file in the SD card\n");
return;
}
#else
// 0. Download the YUV file thru USB.
//-------------------------------------------
SetEncMode(&sel);
uYuvFileAddr = uFreeMemBuf;
Disp(" Before testing, download \"%s\" file through USB \n", pSrcYUVFileName);
uYuvFileSize = DownloadImageThruUsbOtg((u8 *)uYuvFileAddr);
if (uYuvFileSize == 0)
return;
uFreeMemBuf += uYuvFileSize;
uFreeMemBuf = (uFreeMemBuf+STREAM_WR_SIZE-1)/STREAM_WR_SIZE*STREAM_WR_SIZE;
#endif
// 1. Move firmware and init base settings.
//-------------------------------------------
MFC_MoveFirmwareToCodeBuf(uFreeMemBuf);
MFC_GetCodeBufEndAddr(&uFreeMemBuf);
MFC_StartBitProcessor();
MFC_InitBaseForProcesses(uFreeMemBuf);
MFC_GetBaseBufEndAddr(&uFreeMemBuf);
MFC_SetNoFlushingStreamBufModeInEncoding();
// 2. Set encoding parameters.
//-----------------------------
uProcessIdx = 0;
MFC_SetEncYuvFileCfg(uProcessIdx, pSrcYUVFileName, uEncTotalFrameNum, uEncWidth, uEncHeight, 30);
MFC_SetEncSliceCfg(uProcessIdx, 1, 0, 4000);
MFC_SetEncErrResilienceCfg(uProcessIdx, 0);
if (eEncMode == MP4_ENC)
{
if (bIsH263)
MFC_SetEnc263Cfg(uProcessIdx, 0, 1, 0, 0, 10, 15);
else
MFC_SetEncMpeg4Cfg(uProcessIdx, 0, 0, 0, 10, 15);
}
else if (eEncMode == AVC_ENC)
{
MFC_SetEnc264Cfg(uProcessIdx, 0, 0, 0, 0, 0, 15, 15);
}
MFC_SetEncRateCtrlCfg(uProcessIdx, 1, 128, 0, 0);
uYuvFrameSize = uEncWidth * uEncHeight * 3/2;
pEncModeName =
(eEncMode == MP4_ENC && bIsH263) ? "H.263" :
(eEncMode == MP4_ENC && !bIsH263) ? "MPEG4" : "H.264";
Disp("Source file Name: %s, enc mode: %s, w:%d, h:%d, uEncTotalFrameNum:%d\n",
pSrcYUVFileName, pEncModeName, uEncWidth,uEncHeight,uEncTotalFrameNum);
// 3. Keep one frame sized memory and index of the selected YUV file
//-----------------------------------------------------------------
uYuvBufAddr = uFreeMemBuf;
uFreeMemBuf += (uYuvFrameSize/512 + 2) * 512;
// 4. Init a process of MFC
//--------------------------
uFreeMemBuf = (uFreeMemBuf+STREAM_WR_SIZE-1)/STREAM_WR_SIZE*STREAM_WR_SIZE;
uStreamBufStAddr = uFreeMemBuf;
MFC_InitProcessForEncoding(
uProcessIdx, eEncMode, uStreamBufStAddr, STREAM_BUF_SIZE, uEncWidth, uEncHeight, false);
MFC_GetProcessBufEndAddr(uProcessIdx, &uFreeMemBuf);
INTC_SetVectAddr(NUM_MFC,Isr_Mfc);
INTC_Enable(NUM_MFC);
// 5. Init LCDC
//---------------
uLcdFbAddr = uFreeMemBuf;
eLcdBpp = RGB24;
LCD_InitDISPC(eLcdBpp, uLcdFbAddr, WIN0, false);
LCD_GetFbEndAddr(&uFreeMemBuf, WIN0);
LCD_GetFrmSz(&uLcdWidth, &uLcdHeight, WIN0);
uDecWidth = uLcdWidth;
uDecHeight = uLcdHeight*9/10;
GLIB_InitInstance(uLcdFbAddr, uLcdWidth, uLcdHeight, eLcdBpp);
GLIB_ClearFrame(C_BLUE);
GLIB_SetFontColor(C_WHITE, C_BLUE, false);
GLIB_Printf(2, uDecHeight+6, "S3C6400 MFC Encoder(%s)",
(eEncMode == MP4_ENC && bIsH263) ? "H.263" : (eEncMode == MP4_ENC && !bIsH263) ? "MPEG4" : "H.264");
// 6. Init POST
//---------------
MFC_GetAddrOfYFrame(uProcessIdx, 0, &uRecFrmAddrY); // Start addr of MFC's output frame buffers
MFC_GetDispFrameNum(uProcessIdx, &uDispFrameNum);
POST_InitIp1(
uEncWidth, uEncHeight, 0, 0, uEncWidth, uEncHeight, uRecFrmAddrY, YC420,
uLcdWidth, uLcdHeight, 0, 0, uDecWidth, uDecHeight, uLcdFbAddr, eLcdBpp,
uDispFrameNum, false, ONE_SHOT, POST_DMA, POST_DMA, &oPost);
INTC_SetVectAddr(NUM_POST0, Isr_Post);
INTC_Enable(NUM_POST0);
POST_EnableInterrupt(POST_LEVEL_INT, &oPost);
fTotEncTime=0;
uFrameCount=0;
uSrcYuvFileOffset = 0;
uSaveBufAddr = uFreeMemBuf;
uFreeMemBuf += STREAM_BUF_SIZE*4;
LCD_Start();
while (GetKey() == 0)
{
// 7. Read one frame of YUV image from SD card
//---------------------------------------------
#if USE_SD_STORAGE
if (!FAT_ReadFile6(sel, uSrcYuvFileOffset, uYuvFrameSize, uYuvBufAddr, &uTrueStAddrOfData, &oSdhc))
break;
#else
if((uSrcYuvFileOffset+uYuvFrameSize)<=uYuvFileSize)
{
memcpy((void *)uYuvBufAddr, (void *)(uYuvFileAddr+uSrcYuvFileOffset), uYuvFrameSize);
uTrueStAddrOfData = uYuvBufAddr;
}
else
break;
#endif
uSrcYuvFileOffset += uYuvFrameSize;
// 8. Encode one frame
//---------------------
StartTimer(0);
bMfcDone = false;
MFC_SetEncRunOption(false, false);
MFC_StartEncodingOneFrame(uProcessIdx, uTrueStAddrOfData);
while(bMfcDone != true);
MFC_DoPostProcessingOfEncoding(uProcessIdx, &uRecFrameIdx);
fEncTime = StopTimer(0);
fTotEncTime += fEncTime;
// 9. Save the encoded stream of the size of the write unit
//----------------------------------------------------------
uFrameCount++;
MFC_GetWrPtr(uProcessIdx, &uWrPtr);
if (uWrPtr > uStreamBufStAddr+((uStreamOffset+nWriteUnit)%STREAM_BUF_SIZE)+STREAM_WR_SIZE)
{
//Copy32(uStreamBufStAddr+(uStreamOffset%STREAM_BUF_SIZE), uSaveBufAddr+uStreamOffset, nWriteUnit/4);
memcpy((void *)(uSaveBufAddr+uStreamOffset), (void *)(uStreamBufStAddr+(uStreamOffset%STREAM_BUF_SIZE)), nWriteUnit);
uStreamOffset += nWriteUnit;
MFC_SetRdPtr(uProcessIdx, uWrPtr-STREAM_WR_SIZE); // to avoid the full status
}
// 10. Convert the frame for display for verifying
//-------------------------------------------------
bPostDone = false;
POST_StartProcessing1(uRecFrameIdx, 0, &oPost);
while(bPostDone == false);
LCD_Trigger();
if (uFrameCount == uEncTotalFrameNum)
{
Disp("Encoding is ended with %d frames\n", uFrameCount);
break;
}
}
MFC_IssueSeqEndCmd(uProcessIdx);
// As we called MFC_SetNoFlushingStreamBufModeInEncoding(),
// we need copy operation once more after calling MFC_IssueSeqEndCmd().
MFC_GetWrPtr(uProcessIdx, &uWrPtr);
uTransferSize = uWrPtr - (uStreamBufStAddr+(uStreamOffset%STREAM_BUF_SIZE));
//Copy32(uStreamBufStAddr+
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -