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

📄 enctest.cpp

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 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 + -