📄 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"
#include "test.h"
//#define USE_PRP_PHYSICAL_ADDRESS
#define ENC_DEC_SYNC
#define NUM_FRAME_BUF (1 + 17 + 2)
#define DEFAULT_SEARCHRAM_ADDR (0xFFFF4C00)
extern BOOL g_fLoopTest;
extern double fHighFre;
#ifdef ENC_DEC_SYNC
HANDLE hDecoding;
#endif
static PhysicalAddress BitstreamPhy;
static UINT8* pBitStream;
static PhysicalAddress FrameBufPhy;
static UINT8* pFrameBuf;
static HANDLE hFileOutput;
static HANDLE hFillBufEvent, hFillBufEventFinish;
static FrameBuffer* pAvailableFrameBuf;
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;
#ifdef PROFILE_TIME
LARGE_INTEGER liStartTime = {0}, liStopTime = {0};
LARGE_INTEGER liTime = {0};
LARGE_INTEGER liHWTime = {0};
LARGE_INTEGER litmp = {0};
#endif
int srcFrameIdx, secondsrcFrameIdx = 0, tmpFrameIdx = 0;
UINT YFrameSize;
int tmp;
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 ;
}
#ifdef ENC_DEC_SYNC
hDecoding = CreateEvent(NULL, FALSE, FALSE, NULL);
if(hDecoding == NULL){
CloseHandle(RunEvent);
return ;
}
#endif
#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
if(!LoadCamDriver()) {
CloseHandle(RunEvent);
return;
}
//bitstream buffer init ...
if (RETCODE_SUCCESS != vpu_AllocPhysMem(CODEC_BITSTREAM_SIZE, &bitstreambuf)) {
goto ERR_ENC_OPEN;
}
pBitStream = (UINT8 *)bitstreambuf.VirtAdd;
BitstreamPhy = bitstreambuf.PhysAdd;
// Fill parameters for encoding.
encOP.bitstreamBuffer = BitstreamPhy;
encOP.bitstreamBufferSize = CODEC_BITSTREAM_SIZE;
encOP.bitstreamFormat = stdMode;
encOP.picWidth = picWidth;
encOP.picHeight = picHeight;
encOP.frameRateInfo = 30;
encOP.bitRate = bitRate;
encOP.initialDelay = 0;
encOP.vbvBufferSize = 0; // 0 = ignore
encOP.enableAutoSkip = 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;
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);
while (g_fLoopTest) {
#ifdef PROFILE_TIME
if(frameIdx == 100) {
QueryPerformanceCounter(&liTime);
}
else if(frameIdx == PROFILE_FRMAE_END_NUM) {
litmp = liTime;
QueryPerformanceCounter(&liTime);
liTime.QuadPart -= litmp.QuadPart;
}
#endif
// 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
if((frameIdx >= 100) && (frameIdx < 4100))
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
if((frameIdx >= 100) && (frameIdx < PROFILE_FRMAE_END_NUM)) {
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)) {
RETAILMSG(1, (_T("SaveBSBuffer failed! \n")));
break;
}
#ifdef ENC_DEC_SYNC
SetEvent(hDecoding);
#endif
RETAILMSG(1, (_T("frame %d\n"),frameIdx++));
}
#ifdef PROFILE_TIME
printf("Enc: total frames:%d", frameIdx);
printf("Enc: Average time of HW: %f(ms)\n",liHWTime.QuadPart/(fHighFre*PROFILE_FRMAE_NUM)*1000);
printf("Enc: Averate total time: %f(ms)\n",liTime.QuadPart/(fHighFre*PROFILE_FRMAE_NUM)*1000);
#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();
}
DWORD WINAPI EncodeProc(LPVOID lpParameter)
{
CodStd stdMode;
int picWidth,picHeight, bitRate;
stdMode = CODEC_STD;
picWidth = IMAGE_WIDTH;
picHeight = IMAGE_HEIGHT;
bitRate = 512;
EncodeTest(stdMode, picWidth, picHeight, bitRate);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -