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

📄 vidcap.c

📁 这是基于韩国芯片EQUATOR公司的图像缩放程序
💻 C
字号:
/**
*** Copyright (c) 2001-2002 Equator Technologies, Inc.
**/

/************************************************************************
***
***  FILENAME: vidcap.c
***
***  DESCRIPTION:
***    Test application for video capture and display.
***
***    This application captures and displays PAL or NTSC video.
***
***    Note: The Shark board only has one video input path.
***
************************************************************************/

#include <stdlib.h>
#include <stdio.h>

#include <eti/drv.h>
#include "vidcap.h"


// Constants

#define NUM_BUF_IN 4
#define NUM_BUF_OUT 4
#define CHANNEL_SWITCH_PERIOD 150  // in frames
#define USE_VCXO 0  // define if VCXO usage is preferred to fixed clock

// Macro for checking a driver return code
#define CHECK_RC(rc, fnname) \
    if (ETIDRV_CHECK_ERROR(rc)) { \
        printf(fnname ## " failed, error = 0x%08x\n", rc); \
        exit(1); \
    }

typedef enum {
  SYNC_STATE_OK,
  SYNC_STATE_VIN_HALTED,
  SYNC_STATE_LOST,
  SYNC_STATE_SIZEOF
} SyncState;


// Static variables 

static DrvHandle VdisHandle = NULL;
static DrvHandle BufHandleIn[2] = { NULL, NULL };
static DrvHandle VcapHandle[2] = { NULL, NULL };
static DrvHandle VinHandle[2] = { NULL, NULL };

// Turns each source on or off. This value is set by a command line argument.
static BOOL bUsePort[2] = { TRUE, FALSE };     

static SyncState SyncLost[2] = { SYNC_STATE_OK, SYNC_STATE_OK };

static UINT8 *pBufferBlockOut = NULL;
static UINT8 *pBufferBlockIn[2] = { NULL, NULL };

static UINT8 *pCurBufIn = NULL;
static UINT8 *pCurBufOut = NULL;

// Functions

static void RestartCallback (void *pArg)
{
    int portNum = pArg ? 1 : 0;

    //
    // do as little as possible in the interrupt handler for end
    // of frame. Halt the video in to avoid any overflows, and do
    // the rest in CheckSync later.
    //
    if (SyncLost[portNum] == SYNC_STATE_LOST)
    {
        EtiVinHalt(VinHandle[portNum]);
        SyncLost[portNum] = SYNC_STATE_VIN_HALTED;
    }
}


//
// This code checks to see if sync has been lost, and restarts
// video capture.
//
static SCODE CheckSync (int iPortCount, int iFrameCount)
{
    SCODE err = ETIDRV_OK;
    VIN_STATUS VinStatus;

    if (SyncLost[iPortCount] == SYNC_STATE_VIN_HALTED) {
        //
        // If sync was lost on the previous frame, restart video capture.
        //
        printf("Sync lost on frame %d... restarting Vin and continuing DS\n", iFrameCount);

        err = EtiBufInvalidateDsBuffer(BufHandleIn[iPortCount]);
        CHECK_RC(err, "EtiBufInvalidateDsBuffer");

        err = EtiBufContinue(BufHandleIn[iPortCount]);
        CHECK_RC(err, "EtiBufContinue");

        err = EtiVinKick(VinHandle[iPortCount]);
        CHECK_RC(err, "EtiVinKick");

        SyncLost[iPortCount] = SYNC_STATE_OK;
    }
    else if (SyncLost[iPortCount] == SYNC_STATE_OK) {
        //
        // If sync wasn't lost on the previous frame, see if 
        // it was lost on this frame
        //

        // Check the state of the "LessLine" field of Vin status
        err = EtiVinGetStatus(VinHandle[iPortCount], &VinStatus, TRUE);
        CHECK_RC(err, "EtiVinGetStatus");

        // If sync was lost, halt the DS at the end of the next transfer so that it
        // stops on a clean buffer boundary. Restart capture in the next loop.
        if (VinStatus.bLessLine) {
            printf("Lessline on frame %d... halting DS\n", iFrameCount);

            SyncLost[iPortCount] = SYNC_STATE_LOST;

            err = EtiBufPause(BufHandleIn[iPortCount]);
            CHECK_RC(err, "EtiBufPause");
        }
    }

    return err;
}


//
// Vidcap initialization, allocation of all buffers, media drivers resources,
// etc.
//
SCODE InitVidcap (BOOL bUsePal, BOOL bUsePort0, BOOL bUsePort1)
{
    SCODE err = ETIDRV_OK;
    DrvHandle BoardHandle = NULL;
    BOARD_COMMAND BoardCommand;
    VCAP_SETTINGS VcapSettings;
    VDIS_SETTINGS VdisSettings;
    UINT32 uiDisplayType = 0;
    int iPortCount;
    int iBufCount;
    ETI_VIDBUFINFO BufInfo;
    int iWidth, iHeight;

    err = EtiDriverInit();
   // CHECK_RC(err, "EtiDriverInit");

    bUsePort[0] = bUsePort0;
    bUsePort[1] = bUsePort1;

    err = EtiBoardOpen(&BoardHandle, ETI_OPENMODE_MODIFY, 0);
   // CHECK_RC(err, "EtiBoardOpen");

#if USE_VCXO
    // This command will cause the Stingray or Dolphin to use the 
    // VCXO rather than the fixed reference clock 
    err = EtiBoardCommand(BoardHandle, COMMAND_VCXO_CLOCK, 0);
  //  CHECK_RC(err, "EtiBoardCommand");
#endif

    if (bUsePal) {

        // Set board chips for PAL input and output
        err = EtiBoardCommand(BoardHandle, COMMAND_PAL_VID_INPUT, 0);
	
       // CHECK_RC(err, "EtiBoardCommand");

        err = EtiBoardCommand(BoardHandle, COMMAND_PAL_VID_INPUT, 1);
        //CHECK_RC(err, "EtiBoardCommand");

        err = EtiBoardCommand(BoardHandle, COMMAND_PAL_VID_OUTPUT, 0);
       // CHECK_RC(err, "EtiBoardCommand");
    }

    // See if alternate video input was selected
    for (iPortCount = 0; iPortCount < 2; iPortCount++) {
        if (bUsePort[iPortCount] > 1) {
            switch (bUsePort[iPortCount]) {
            case 2:
                BoardCommand = COMMAND_COMP1_VID_INPUT;
                break;
            case 3:
                BoardCommand = COMMAND_COMP2_VID_INPUT;
                break;
            default:
                printf("Error: bUsePort is to large\n");
                exit(1);
            }
            err = EtiBoardCommand(BoardHandle, BoardCommand, iPortCount);
            //CHECK_RC(err, "EtiBoardCommand");
        }
    }

    err = EtiBoardClose(BoardHandle);
    //CHECK_RC(err, "EtiBoardClose");
    BoardHandle = NULL;

    //
    // Set up the drivers and buffers for each input port requested
    //
    for (iPortCount = 0; iPortCount < 2; iPortCount++) {
        if (bUsePort[iPortCount]) {

            // Open Vcap driver
            err = EtiVcapOpen(&(VcapHandle[iPortCount]), ETI_OPENMODE_MODIFY, iPortCount);
            CHECK_RC(err, "EtiVcapOpen");

            // Get default settings
            VcapSettings.iVersion = ETI_DRIVER_VER;
            err = EtiVcapDefault(VcapHandle[iPortCount], &VcapSettings, bUsePal);
            CHECK_RC(err, "EtiVcapDefault");

            // Store values from video capture for use in video display functions
            BufInfo = VcapSettings.BufInfo;
            iWidth = BufInfo.u.LayoutOffsets.iYWidth;
            iHeight = BufInfo.u.LayoutOffsets.iYHeight;

            printf("Image size is %d x %d\n", iWidth, iHeight);


            // Open video capture
            VcapSettings.BufSettings.pEobCallback = RestartCallback;
            VcapSettings.BufSettings.pEobData = (void *) iPortCount;
            err = EtiVcapSetup(VcapHandle[iPortCount], &VcapSettings);
            CHECK_RC(err, "EtiVcapSetup");
            
            BufHandleIn[iPortCount] = EtiVcapGetBufHandle(VcapHandle[iPortCount]);
            VinHandle[iPortCount] = EtiVcapGetVinHandle(VcapHandle[iPortCount]);

            // Allocate buffers
            pBufferBlockIn[iPortCount] = malloc(NUM_BUF_IN * ETI_MAX_FRAMESIZE);
            if (!pBufferBlockIn[iPortCount]) {
                printf("Memory allocation failed\n");
                exit(1);
            }

            printf("Buffers located at 0x%08x\n", pBufferBlockIn[iPortCount]);
            
            // Queue up the buffers
            pCurBufIn = pBufferBlockIn[iPortCount];
			
	     printf("___________ x\n");

            for (iBufCount = 0; iBufCount < NUM_BUF_IN; iBufCount++) {
                err = EtiBufBufferReady(BufHandleIn[iPortCount], pCurBufIn, NULL, 0);
                CHECK_RC(err, "EtiBufBufferReady");
                pCurBufIn += ETI_MAX_FRAMESIZE;
            }
	     printf("___________ y\n");
	
        }
    }

    //
    // Set up video display
    //
    uiDisplayType = bUsePal ? VDIS_DISPLAYTYPE_625 : VDIS_DISPLAYTYPE_525;

    // Open Vdis driver
    err = EtiVdisOpen(&VdisHandle, ETI_OPENMODE_MODIFY, 0);
    CHECK_RC(err, "EtiVdisOpen");

    // Get default settings video display
    VdisSettings.iVersion = ETI_DRIVER_VER;
    err = EtiVdisDefault(VdisHandle, &VdisSettings, uiDisplayType,
                         iWidth, iHeight, 0, FALSE);
    CHECK_RC(err, "EtiVdisDefault");

    EtiUtilPrintVidBufInfo(&BufInfo);

    // Add buffer as a surface
    err = EtiVdisAddSurface(VdisHandle, &VdisSettings, VDIS_STREAM_V2,
                            &BufInfo, 0, 0, 0, 0, 100);
    CHECK_RC(err, "EtiVdisAddSurface");

    // If the reference clock is being used, the VCXO can be disabled
    // with the following line:
    // VdisSettings.bVcxoOff = TRUE;

    // Open video display driver
    err = EtiVdisSetup(VdisHandle, &VdisSettings);
    CHECK_RC(err, "EtiVdisSetup");

    // Allocate output buffers
    pBufferBlockOut = calloc(NUM_BUF_OUT, ETI_MAX_FRAMESIZE);
    if (!pBufferBlockOut) {
        printf("Memory allocation failed\n");
        exit(1);
    }

    // Queue up all but the last display buffer
    pCurBufOut = pBufferBlockOut;

    for (iBufCount = 0; iBufCount < NUM_BUF_OUT - 1; iBufCount++) {
        err = EtiVdisBufferReady(VdisHandle, VDIS_STREAM_V2, pCurBufOut, NULL);
        CHECK_RC(err, "EtiVdisBufferReady");

        pCurBufOut += ETI_MAX_FRAMESIZE;
    }
    // Last buffer will be used by the first iteration of the loop

    //
    // Start video capture
    //
    for (iPortCount = 0; iPortCount < 2; iPortCount++) {
        if (bUsePort[iPortCount]) {
            err = EtiVcapKick(VcapHandle[iPortCount]);
            CHECK_RC(err, "EtiVcapKick");
        }
    }

    //
    // Start display
    //
    err = EtiVdisKick(VdisHandle);
    CHECK_RC(err, "EtiVdisKick");

    return err;
}


//
// Processes a single buffer from capture side, passing it over to display
//
SCODE ProcessVidcapSingle (int iFrameCount)
{
    SCODE err = ETIDRV_OK;
    BOOL bBothChannels = bUsePort[0] && bUsePort[1];
    int iPortCount;
    static int iDisplayPort = 0;

    for (iPortCount = 0; iPortCount < 2; iPortCount++) {
       if (bUsePort[iPortCount]) {

	     printf("___________ 1\n");
            // Get a video frame
            err = EtiBufGetBuffer(BufHandleIn[iPortCount], (void **) &pCurBufIn,
                                  NULL, BUF_INFINITE_WAIT);
            CHECK_RC(err, "EtiBufGetBuffer");

            err = CheckSync (iPortCount, iFrameCount);
            CHECK_RC(err, "CheckSync");
    
            // Process video frame here
            if (!bBothChannels || iPortCount == iDisplayPort) {
                memcpy(pCurBufOut, pCurBufIn, ETI_MAX_FRAMESIZE);
            }
           printf("___________ 2\n");

            // Give the input buffer back to the capture driver
            err = EtiBufBufferReady(BufHandleIn[iPortCount], pCurBufIn, NULL, 0);
            CHECK_RC(err, "EtiBufBufferReady");
	     printf("___________ 3\n");
			
        }
	 printf("___________ ok\n");
    }
   
    // Send the output buffer to the display driver
    err = EtiVdisBufferReady(VdisHandle, VDIS_STREAM_V2, pCurBufOut, NULL);
    CHECK_RC(err, "EtiVdisBufferReady");

    // Get a new output buffer
    err = EtiVdisGetBuffer(VdisHandle, VDIS_STREAM_V2, (void **) &pCurBufOut,
                           NULL, BUF_INFINITE_WAIT);
    CHECK_RC(err, "EtiVdisGetBuffer");

    // Check the video display FIFOs
    err = EtiVdisCheckFifos(VdisHandle, TRUE);
    if (ETIDRV_CHECK_NOT_OK(err)) {
        printf("EtiVdisCheckFifos failed, error = 0x%08x\n", err);
    }

    if (iFrameCount % CHANNEL_SWITCH_PERIOD == 0) {
        iDisplayPort ^= 1;
    }
    if ((iFrameCount & 0xffff) == 0xffff)
        printf ("%d frames processed\n", iFrameCount);
}


//
// Frees all allocated resources
//
SCODE CloseVidcap (void)
{
    SCODE err = ETIDRV_OK;
    int iPortCount;

    //
    // Close all the drivers and free all memory
    //
    for (iPortCount = 0; iPortCount < 2; iPortCount++) {
        if (bUsePort[iPortCount]) {

            err = EtiVcapClose(VcapHandle[iPortCount]);
            CHECK_RC(err, "EtiVcapClose");
            VcapHandle[iPortCount] = NULL;

            free(pBufferBlockIn[iPortCount]);
        }
    }

    err = EtiVdisClose(VdisHandle);
    CHECK_RC(err, "EtiVdisClose");
    VdisHandle = NULL;

    free(pBufferBlockOut);

    //
    // Check to make sure all memory that was allocated by the
    // drivers was properly freed
    //
    EtiUtilListAllocatedMemory();
}


//
// Main processing function
//
SCODE ProcessVidcap(BOOL bUsePal,        // Set to 0 to capture/display NTSC
                    BOOL bUsePort0,      // Capture from video port 0
                    BOOL bUsePort1,      // Capture from video port 1
                    int iFramesToCapture // Number of frames to capture (0=capture forever)
                  )
{
    SCODE err = ETIDRV_OK;
    int iFrameCount;

    err = InitVidcap (bUsePal, bUsePort0, bUsePort1);
    CHECK_RC (err, "InitVidcap");

    //
    // Loop the desired number of frames (0 = forever)
    //
    iFrameCount = 0;
    while (iFramesToCapture == 0 ||
           iFrameCount < iFramesToCapture) {
        err = ProcessVidcapSingle (iFrameCount);
        CHECK_RC (err, "ProcessVidcapSingle");
        ++iFrameCount;
    }

    err = CloseVidcap ();
    CHECK_RC (err, "CloseVidcap");

    return err;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -