📄 enctest.cpp
字号:
//-----------------------------------------------------------------------------
//
// Copyright (C) 2006, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//-----------------------------------------------------------------------------
//
// File: dectest.cpp
//
// Provides the encoder implementation using VPU APIs.
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include "bsp.h"
#include "vpu_api.h"
#include "camerafunc.h"
//#define USE_PRP_PHYSICAL_ADDRESS
#define TEST_FRAME_NUM 50
#define PROFILE_TIME
#define DEFAULT_SEARCHRAM_ADDR (0xFFFF4C00)
#define NUM_FRAME_BUF (1 + 17 + 2)
BOOL g_fLoopTest = TRUE;
static PhysicalAddress BitstreamPhy;
static UINT8* pBitStream;
static PhysicalAddress FrameBufPhy;
static UINT8* pFrameBuf;
static HANDLE hFileOutput;
static HANDLE hliu;
static HANDLE hFillBufEvent, hFillBufEventFinish;
static FrameBuffer* pAvailableFrameBuf;
int SaveBSBuffer(UINT8* bsBuf0, size_t size0)
{
DWORD writenum;
if(!hFileOutput) return 0;
WriteFile(hFileOutput, (void*)bsBuf0, size0, &writenum, NULL);
return writenum;
}
static DWORD WINAPI FillYUVThread(LPVOID lpParameter)
{
CeSetThreadPriority(GetCurrentThread(), 121);
while(1){
WaitForSingleObject(hFillBufEvent, INFINITE);
PerFrameCameraCapture(pFrameBuf + (pAvailableFrameBuf->bufY - FrameBufPhy));
SetEvent(hFillBufEventFinish);
}
return 0;
}
// This function demonstrates how to encode using vpu API.
static void EncodeTest(CodStd stdMode, int picWidth, int picHeight, int bitRate)
{
EncHandle handle;
EncOpenParam encOP;
EncParam encParam;
SearchRamParam searchPa = { 0 };
EncHeaderParam encHeaderParam = { 0 };
EncInitialInfo initialInfo;
EncOutputInfo outputInfo;
RetCode ret;
PhysicalAddress bsBuf0;
Uint32 size0;
int srcFrameIdx, secondsrcFrameIdx = 0, tmpFrameIdx = 0;
UINT YFrameSize;
int tmp;
#ifdef PROFILE_TIME
LARGE_INTEGER liStartTime = {0}, liStopTime = {0};
LARGE_INTEGER liTime = {0};
LARGE_INTEGER liHWTime = {0};
LARGE_INTEGER litmp = {0};
#endif
double fHighFre = 0;
PRP_BUFFER PrpBuffer = {0};
FrameBuffer frameBufTmp = {0};
FrameBuffer frameBuf[NUM_FRAME_BUF];
int i;
int frameIdx;
int exit;
int stride;
HANDLE RunEvent = NULL;
#ifndef USE_PRP_PHYSICAL_ADDRESS
HANDLE hFillBufIST = NULL;
#endif
VPUMemAlloc bitstreambuf = {0};
VPUMemAlloc framebuffers = {0};
RunEvent = CreateEvent(NULL, FALSE, FALSE, VPU_INT_PIC_RUN_NAME);
if(RunEvent == NULL) {
return ;
}
#ifndef USE_PRP_PHYSICAL_ADDRESS
hFillBufEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if(RunEvent == NULL) {
CloseHandle(RunEvent);
return ;
}
hFillBufEventFinish = CreateEvent(NULL, FALSE, FALSE, NULL);
if(hFillBufEventFinish == NULL) {
CloseHandle(RunEvent);
CloseHandle(hFillBufEvent);
return ;
}
// Create IST thread to fill YUV image
hFillBufIST = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)FillYUVThread, NULL, 0, NULL);
if(hFillBufIST == NULL) {
CloseHandle(RunEvent);
CloseHandle(hFillBufEvent);
CloseHandle(hFillBufEventFinish);
return;
}
#endif
// Initiate vpu*/
ret = vpu_Init();
if( ret != RETCODE_SUCCESS &&
ret != RETCODE_CALLED_BEFORE ) {
DEBUGMSG(1, (_T("vpu_Init failed Error code is 0x%x \n"), ret));
goto ERR_ENC_INIT;
}
if(!LoadCamDriver()) {
CloseHandle(RunEvent);
return;
}
//bitstream buffer init ...
if (RETCODE_SUCCESS != vpu_AllocPhysMem(0x050000, &bitstreambuf)) {
goto ERR_ENC_OPEN;
}
pBitStream = (UINT8 *)bitstreambuf.VirtAdd;
BitstreamPhy = bitstreambuf.PhysAdd;
// Fill parameters for encoding.
encOP.bitstreamBuffer = BitstreamPhy;
encOP.bitstreamBufferSize = 0x050000;
encOP.bitstreamFormat = stdMode;
encOP.picWidth = picWidth;
encOP.picHeight = picHeight;
encOP.frameRateInfo = 30;
encOP.bitRate = 0;
encOP.initialDelay = 0;
encOP.vbvBufferSize = 0; // 0 = ignore
encOP.enableAutoSkip = 1; // for compare with C-model ( C-model = only 1 )
encOP.gopSize = 0; // only first picture is I
encOP.slicemode.sliceMode = 0; // 1 slice per picture
encOP.slicemode.sliceSizeMode = 0;
encOP.slicemode.sliceSize = 0;
encOP.intraRefresh = 0;
encOP.sliceReport = 0;
encOP.mbReport = 0;
encOP.mbQpReport = 0;
encOP.rcIntraQp =-1;
if(stdMode == STD_MPEG4) {
encOP.EncStdParam.mp4Param.mp4_dataPartitionEnable = 0;
encOP.EncStdParam.mp4Param.mp4_reversibleVlcEnable = 0;
encOP.EncStdParam.mp4Param.mp4_intraDcVlcThr = 0;
encOP.EncStdParam.mp4Param.mp4_hecEnable = 0;
encOP.EncStdParam.mp4Param.mp4_verid = 2;
}
else if(stdMode == STD_H263) {
encOP.EncStdParam.h263Param.h263_annexJEnable = 0;
encOP.EncStdParam.h263Param.h263_annexKEnable = 0;
encOP.EncStdParam.h263Param.h263_annexTEnable = 0;
}
else if(stdMode == STD_AVC) {
encOP.EncStdParam.avcParam.avc_constrainedIntraPredFlag = 0;
encOP.EncStdParam.avcParam.avc_disableDeblk = 2;
encOP.EncStdParam.avcParam.avc_deblkFilterOffsetAlpha = -3;
encOP.EncStdParam.avcParam.avc_deblkFilterOffsetBeta = -5;
encOP.EncStdParam.avcParam.avc_chromaQpOffset = 4;
encOP.EncStdParam.avcParam.avc_audEnable = 0;
encOP.EncStdParam.avcParam.avc_fmoEnable = 0;
encOP.EncStdParam.avcParam.avc_fmoType = 0;
encOP.EncStdParam.avcParam.avc_fmoSliceNum = 0;
}
else {
DEBUGMSG(1, (_T("Invalid bitstream format mode \n")));
goto ERR_ENC_INIT;
}
encOP.ringBufferEnable = 0;
encOP.dynamicAllocEnable = 0;
// Open an instance and get initail information for encoding.
ret = vpu_EncOpen(&handle, &encOP);
if(ret != RETCODE_SUCCESS) {
DEBUGMSG(1, (_T("vpu_EncOpen failed Error code is 0x%x \n"), ret));
goto ERR_ENC_INIT;
}
searchPa.searchRamAddr = DEFAULT_SEARCHRAM_ADDR;
ret = vpu_EncGiveCommand( handle, ENC_SET_SEARCHRAM_PARAM, &searchPa);
if(ret != RETCODE_SUCCESS) {
DEBUGMSG(1, (_T("VPU_EncGiveCommand failed Error code is 0x%x \n"), ret));
goto ERR_ENC_OPEN;
}
ret = vpu_EncGetInitialInfo(handle, &initialInfo);
if(ret != RETCODE_SUCCESS) {
DEBUGMSG(1, (_T("vpu_EncGetInitialInfo failed Error code is 0x%x \n"), ret));
goto ERR_ENC_OPEN;
}
YFrameSize = encOP.picWidth * encOP.picHeight;
srcFrameIdx = initialInfo.minFrameBufferCount;
tmp = (int) (YFrameSize*1.5);
#ifdef USE_PRP_PHYSICAL_ADDRESS
//allocate memory for framebuffer
pFrameBuf = (UINT8*)vpu_AllocPhysMem((tmp * (initialInfo.minFrameBufferCount)), &FrameBufPhy);
for (i = 0; i < initialInfo.minFrameBufferCount; i++) {
#else
//allocate memory for framebuffer
if(RETCODE_SUCCESS != vpu_AllocPhysMem((tmp * (initialInfo.minFrameBufferCount+2)), &framebuffers)) {
printf("AllocPhysMem failed\n");
goto ERR_ENC_INIT;
}
pFrameBuf = (UINT8*)framebuffers.VirtAdd;
FrameBufPhy = framebuffers.PhysAdd;
//allocate memory for framebuffer
for (i = 0; i < initialInfo.minFrameBufferCount+2; i++) {
#endif
frameBuf[i].bufY = FrameBufPhy + tmp * i ;
frameBuf[i].bufCb = frameBuf[i].bufY + YFrameSize;
frameBuf[i].bufCr = frameBuf[i].bufCb + YFrameSize/4;
}
stride = picWidth;
// Register frame buffers requested by the encoder.
ret = vpu_EncRegisterFrameBuffer(handle, frameBuf, initialInfo.minFrameBufferCount, stride);
if(ret != RETCODE_SUCCESS) {
DEBUGMSG(1, (_T("vpu_EncRegisterFrameBuffer failed Error code is 0x%x \n"), ret));
goto ERR_ENC_OPEN;
}
exit = 0;
frameIdx = 0;
encParam.sourceFrame = &frameBuf[srcFrameIdx];
encParam.quantParam = 30;
encParam.forceIPicture = 0;
encParam.skipPicture = 0;
// Make encode hedaer
if(stdMode == STD_MPEG4) {
encHeaderParam.headerType = VOL_HEADER;
vpu_EncGiveCommand(handle, ENC_PUT_MP4_HEADER, &encHeaderParam);
if( encOP.ringBufferEnable == 0 )
SaveBSBuffer((pBitStream +(encHeaderParam.PhysBuf - BitstreamPhy)), (size_t)encHeaderParam.size);
}
else if(stdMode == STD_AVC) {
encHeaderParam.headerType = SPS_RBSP;
vpu_EncGiveCommand(handle, ENC_PUT_AVC_HEADER, &encHeaderParam);
if(encOP.ringBufferEnable == 0)
SaveBSBuffer((pBitStream +(encHeaderParam.PhysBuf - BitstreamPhy)), (size_t)encHeaderParam.size);
encHeaderParam.headerType = PPS_RBSP;
vpu_EncGiveCommand(handle, ENC_PUT_AVC_HEADER, &encHeaderParam);
if(encOP.ringBufferEnable == 0)
SaveBSBuffer((pBitStream +(encHeaderParam.PhysBuf - BitstreamPhy)), (size_t)encHeaderParam.size);
}
// update param
encParam.slicemode.sliceMode = encOP.slicemode.sliceMode;
encParam.slicemode.sliceSizeMode = encOP.slicemode.sliceSizeMode;
encParam.slicemode.sliceSize = encOP.slicemode.sliceSize;
encParam.intraRefresh = encOP.intraRefresh;
encParam.hecEnable = 0;
#ifdef USE_PRP_PHYSICAL_ADDRESS
StartCameraCapture(TRUE);
#else
StartCameraCapture(FALSE);
if(!PerFrameCameraCapture(pFrameBuf + (encParam.sourceFrame->bufY - FrameBufPhy)))
goto ERR_ENC_OPEN;
secondsrcFrameIdx = srcFrameIdx + 1;
SetEvent(hFillBufEventFinish);
#endif
CeSetThreadPriority(GetCurrentThread(), 120);
#ifdef PROFILE_TIME
QueryPerformanceFrequency(&litmp);
fHighFre = (double)litmp.QuadPart;
QueryPerformanceCounter(&liTime);
#endif
while (frameIdx < TEST_FRAME_NUM) {
//Load source image to encode to SDRAM frame buffer.
#ifdef USE_PRP_PHYSICAL_ADDRESS
GetPhysicalAddrPerFrame(&PrpBuffer);
frameBufTmp.bufY = (PhysicalAddress)PrpBuffer.pPhysAddr;
frameBufTmp.bufCb = frameBufTmp.bufY + YFrameSize;
frameBufTmp.bufCr = frameBufTmp.bufCb + YFrameSize/4;
encParam.sourceFrame = &frameBufTmp;
#else
WaitForSingleObject(hFillBufEventFinish, INFINITE);
// Fill next frame data
pAvailableFrameBuf = &frameBuf[secondsrcFrameIdx];
SetEvent(hFillBufEvent);
// Start encoding a frame.
encParam.sourceFrame = &frameBuf[srcFrameIdx];
#endif
ret = vpu_EncStartOneFrame(handle, &encParam);
#ifdef PROFILE_TIME
QueryPerformanceCounter(&liStartTime);
#endif
if(ret != RETCODE_SUCCESS) {
DEBUGMSG(1, (_T("vpu_EncStartOneFrame failed Error code is 0x%x \n"), ret));
goto ERR_ENC_OPEN;
}
WaitForSingleObject(RunEvent, INFINITE);
#ifdef PROFILE_TIME
QueryPerformanceCounter(&liStopTime);
liHWTime.QuadPart += (liStopTime.QuadPart - liStartTime.QuadPart);
#endif
#ifdef USE_PRP_PHYSICAL_ADDRESS
ReturnPhysicalAddrPerFrame(&PrpBuffer);
#else
// Prepare for filling next YUV data
tmpFrameIdx = secondsrcFrameIdx;
secondsrcFrameIdx = srcFrameIdx;
srcFrameIdx = tmpFrameIdx;
#endif
// vpu_EncGetOutputInfo() should match vpu_EncStartOneFrame() with
// the same handle. No other API functions can intervene between these two
// functions, except for vpu_IsBusy(), vpu_DecGetBistreamBuffer(),
// and vpu_DecUpdateBitstreamBuffer() with other handle.
ret = vpu_EncGetOutputInfo(handle, &outputInfo);
if(ret != RETCODE_SUCCESS) {
DEBUGMSG(1, (_T("vpu_EncGetOutputInfo failed Error code is 0x%x \n"), ret));
goto ERR_ENC_OPEN;
}
if(outputInfo.bitstreamWrapAround == 1)
printf("Warnning!! BitStream buffer wrap arounded. prepare more large buffer \n");
// Now the bitstream for the current one frame is available.
bsBuf0 = outputInfo.bitstreamBuffer;
size0 = outputInfo.bitstreamSize;
if((SaveBSBuffer((pBitStream +(bsBuf0 - BitstreamPhy)), (size_t)size0) != size0))
break;
frameIdx++;
}
#ifdef PROFILE_TIME
litmp = liTime;
QueryPerformanceCounter(&liTime);
liTime.QuadPart -= litmp.QuadPart;
printf("Enc: Average time of HW: %f(ms)\n",liHWTime.QuadPart*1000/(fHighFre*frameIdx));
printf("Enc: Averate total time: %f(ms)\n",liTime.QuadPart*1000/(fHighFre*frameIdx));
#endif // Now that we are done with encoding, close the open instance.
ERR_ENC_OPEN:
StopCameraCapture();
vpu_EncClose(handle);
if(bitstreambuf.PhysAdd)
vpu_FreePhysMem(&bitstreambuf);
if(framebuffers.PhysAdd)
vpu_FreePhysMem(&framebuffers);
if(RunEvent) {
CloseHandle(RunEvent);
RunEvent = NULL;
}
#ifndef USE_PRP_PHYSICAL_ADDRESS
if(hFillBufEvent) {
CloseHandle(hFillBufEvent);
hFillBufEvent = NULL;
}
if(hFillBufEventFinish) {
CloseHandle(hFillBufEventFinish);
hFillBufEventFinish = NULL;
}
if(hFillBufIST) {
TerminateThread(hFillBufIST, 0);
CloseHandle(hFillBufIST);
hFillBufIST = NULL;
}
#endif
ERR_ENC_INIT:
UnloadCamDriver();
vpu_Deinit();
}
int main()
{
CodStd stdMode;
int picWidth,picHeight, bitRate;
if((hFileOutput =CreateFile(TEXT("\\test.264"), GENERIC_WRITE|GENERIC_READ, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
return 1;
RETAILMSG(CodecDemo_ERROR_MSG, (TEXT("\r\n")));
RETAILMSG(CodecDemo_ERROR_MSG, (TEXT("Start to capture the image ...\r\n")));
stdMode = STD_MPEG4;
picWidth = 320;
picHeight = 240;
bitRate = 0;
EncodeTest(stdMode, picWidth, picHeight, bitRate);
CloseHandle (hFileOutput);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -