首页 > 解决方案 > 基于 Mini PCI 的摄像头图像采集卡,用于使用 API 中的回调函数获取视频流数据

问题描述

我有一个迷你 PCI 采集卡 ( MPX-6864 ),我想用它来从监控摄像头抓取视频流,提供复合 ( PAL/NTSC ) 标准输出。我已经在我的项目中包含了硬件 SDK 提供的DLL 。虽然我能够通过 API 检测/读取有关卡和与卡接口的设备的详细信息,但我无法使用API 的回调函数获取视频流输出。请参考下面的函数。

typedef int (__stdcall *TwVideoStreamCallback)(int nChannel, VOID *DataBuf, int width, int height, BOOL bField2, void *context, __int64 pts);
TW68XX_API BOOL   __stdcall TwRegisterVideoStreamCallback(TwVideoStreamCallback VideoStreamCallback, VOID *Context);

我的疑问是:

  1. 如何调用这些函数并获取数据流。
  2. 如何在封闭 API 中使用 callback 和 callback_register 函数
  3. 两个函数中使用的回调函数的上下文指针是什么

这是特定硬件的 Windows SDK 和驱动程序。其中提供的文档没有多大帮助。

您的帮助将不胜感激。

请参考下面的代码

/* intialise SDK */
        BOOL init = TwInitSDK();
        if (init == 1){
            qDebug() << "Initialization Successfull";
        }
    /* Get board details */
        qDebug() << endl;
        int noOfBoard = TwGetBoardCount();
        qDebug() << "Number of Boards: " << noOfBoard;
        HANDLE bHandle = TwGetBoardHandle(noOfBoard-1);
        qDebug() << "Board Handle is: " << bHandle;
        TBoardDesc pBoardDesc;
        qDebug() << endl;
        qDebug() << "Fetching Board Details....";
        BOOL bDetails = TwGetBoardDetail(bHandle, &pBoardDesc);
        if (bDetails == 1){
            qDebug() << "\t Successful in Fetching Details: ";
            qDebug() << "\t Board Index: " << pBoardDesc.nBoardId;
            qDebug() << "\t Slot no. of board: " << pBoardDesc.nSlot;
            qDebug() << "\t Devices on board: " << pBoardDesc.nDeviceCount;
            qDebug() << "\t Index of first device: " << pBoardDesc.nFirstDevice;
        }
        else{
            qDebug() << "\t Could not Fetch details...";
            qDebug() << "\t Please refer error code: " << TwGetLastError();
        }
    /* Get Device details */
        qDebug() << endl;
        int deviceCount = TwGetDeviceCount();
        qDebug() << "Number of Device: " << deviceCount;
        HANDLE dHandle = TwGetDeviceHandle(deviceCount-1);
        qDebug() << "Device Handle: " << dHandle;
        TDeviceDesc pDevDesc;
        qDebug() << endl;
        qDebug() << "Fetching Device details....";
        BOOL devDetails = TwGetDeviceDetail(dHandle, &pDevDesc);
        if (devDetails == 1){
            qDebug() << "\t Successfull in Fetching Details.... ";
            qDebug() << "\t Device Index: " << pDevDesc.nDeviceId;
            qDebug() << "\t Index of Board where device is: " << pDevDesc.nBoardId;
            qDebug() << "\t Bus number of Board: " << pDevDesc.nBus;
            qDebug() << "\t Device Hardware ID: " << pDevDesc.HardwareId;
            qDebug() << "\t Device Number: " << pDevDesc.DeviceNumber;
            qDebug() << "\t Total dub-device number in device: " << pDevDesc.nSubDevice;
            qDebug() << "\t Index of first sub-device in device: " << pDevDesc.nFirstSubDevice;
        }
        else{
            qDebug() << "\t Could not Fetch details...";
            qDebug() << "\t Please refer error code: " << TwGetLastError();
        }
    /* Get sub-device details */
        qDebug() << endl;
        int subDeviceCount = TwGetSubDeviceCount();
        qDebug() << "Number of Sub-Device: " << subDeviceCount;
        HANDLE sdHandle = TwGetSubDeviceHandle(subDeviceCount-1);
        qDebug() << "Sub-Device Handle: " << sdHandle;
        TSubDeviceDesc pSubDevDesc;
        qDebug() << endl;
        qDebug() << "Fetching Device details....";
        BOOL subDevDetails = TwGetSubDeviceDetail(sdHandle, &pSubDevDesc);
        if (subDevDetails == 1){
            qDebug() << "\t Successfull in Fetching Details.... ";
            qDebug() << "\t Device index where sub-device is: " << pSubDevDesc.nDeviceId;
            qDebug() << "\t Index of Board where sub-device is: " << pSubDevDesc.nBoardId;
            qDebug() << "\t Whether audio is included:" << pSubDevDesc.nAudio;
            qDebug() << "\t The max channel number of non real time switching supported by sub-device: " << pSubDevDesc.iSwitch;
            qDebug() << "\t Total channel number contained by sub-device: " << pSubDevDesc.nChannels;
            qDebug() << "\t Index of the first channel by sub-device: " << pSubDevDesc.nFirstChannel;
            qDebug() << "\t Whether capture odd / even field seperately: " << pSubDevDesc.bField2;
            qDebug() << "\t Video input mask: " << pSubDevDesc.VideoInputMask;
        }
        else{
            qDebug() << "\t Could not Fetch details...";
            qDebug() << "\t Please refer error code: " << TwGetLastError();
        }
    /* Enable input video channel */
        qDebug() << endl;
        BOOL enable = TwEnableVideoInput(sdHandle, viCompositeVideo1, TRUE);
        if (enable == TRUE){
            qDebug() << "Enableing video successfull....";
        }
        else{
            qDebug() << "Enabling Video failed....";
            qDebug() << "Please refer error code: " << TwGetLastError();
        }
    /* Video parameter set before Channel details */
        TVideoPara vPara;
        vPara = vpBufferType;
        BOOL prevSetPara = TwSetVideoPara(NULL, vPara, vbtD1);
        if(prevSetPara == 1){
            qDebug() << "Parameter set before channel details is successfull....";
        }
        else{
            qDebug() << "Parameter setting failed....";
            qDebug() << "Please refer error code: " << TwGetLastError();
        }
    /* Get channel details */
        qDebug() << endl;
        int chCount = TwGetChannelCount();
        qDebug() << "Number of Channels: " << chCount;
        int nChannel = chCount-4; // modify to a typedef struct for nChannel index
        HANDLE chHandle = TwChannelOpen(nChannel);
        qDebug() << "Channel Handle: " << chHandle;
        TChannelDesc pChannelDesc;
        qDebug() << endl;
        qDebug() << "Fetching Channel Details....";
        BOOL chDetails = TwGetChannelDetail(chHandle, &pChannelDesc);
        if (chDetails == 1){
            qDebug() << "\t Successfull in Fetching Details.... ";
            qDebug() << "\t Index of board where channel is: " << pChannelDesc.nBoardId;
            qDebug() << "\t Index of devic where device is: " << pChannelDesc.nDeviceId;
            qDebug() << "\t Index of device where sub-device is: " << pChannelDesc.nSubDeviceId;
            qDebug() << "\t Max frame rate of channel: " << pChannelDesc.nMaxFrameRate;
            qDebug() << "\t Whether audio is contained in channel: " << pChannelDesc.nAudio;
        }
        else{
            qDebug() << "\t Could not Fetch details....";
            qDebug() << "\t Please refer error code: " << TwGetLastError();
        }
    /* Set Video Parameters */
        LONG paraValue;
        TwSetVideoPara(chHandle, vpWidth, 720);
        TwSetVideoPara(chHandle, vpHeight, 576);
        TwSetVideoPara(chHandle, vpFrameRate, 25);
        TwSetVideoPara(chHandle, vpPixelFormat, vpfYUV422Interspersed);
        TwSetVideoPara(chHandle, vpStandard, vsStandardPAL);
        TwSetVideoPara(chHandle, vpBufferType, vbtD1);
    /* Get Video Parameters */
        qDebug() << "\nGetting Video Parameter....";
        TwGetVideoPara(chHandle, vpWidth, &paraValue);
//        int width = paraValue;
        qDebug() << "Video Width: " << paraValue;
        TwGetVideoPara(chHandle, vpHeight, &paraValue);
//        int height = paraValue;
        qDebug() << "Video Height: " << paraValue;
        TwGetVideoPara(chHandle, vpFrameRate, &paraValue);
        qDebug() << "Video Frame Rate: " << paraValue;
        TwGetVideoPara(chHandle, vpPixelFormat, &paraValue);
        qDebug() << "Video PIXEL Format: " << paraValue;
        TwGetVideoPara(chHandle, vpStandard, &paraValue);
        qDebug() << "Video Video Standard: " << paraValue;
        TwGetVideoPara(chHandle, vpBufferType, &paraValue);
        qDebug() << "Video Buffer Type: " << paraValue;
    /* Start Video Capture */
        qDebug() << endl;
        BOOL captureEnable = TwStartVideoCapture(chHandle);
        if (captureEnable == 1){
            qDebug() << "Video Capture Started....";
        }
        else{
            qDebug() << "Could not start video capture...";
            qDebug() << "Please refer error code: " << TwGetLastError();
        }
    /* Obtain Data Stream */

        int extra_context = 42;
        TwVideoStreamCallback my_callback;
        BOOL ret = TwRegisterVideoStreamCallback(my_callback, (void*)&extra_context);
        if (ret) {
            qDebug() << "Data stream available...";
        }
//        qDebug() << extra_context;
//        TwVideoStreamCallback videoStream;
//        VOID *Context;
//        BOOL data = TwRegisterVideoStreamCallback(videoStream, &Context);
//        if (data == 1){
//            qDebug() << "Data stream available...";
//        }
//        else{
//            qDebug() << "Data stream not available...";
//            qDebug() << "Please refer error code: " << TwGetLastError();
//        }
//        videoStream(nChannel, &DataBuf, width, height, FALSE, &context, 0);
//        qDebug() << videoStream;
//        qDebug() << Context;

    /* Stop channel */
        TwChannelClose(chHandle);
    /* Stop Video Capture */
        qDebug() << endl;
        BOOL captureDisable = TwStopVideoCapture(chHandle);
        if (captureDisable == 1){
            qDebug() << "Video Capture Stoped....";
        }
        else{
            qDebug() << "Could not stop video capture...";
            qDebug() << "Please refer error code: " << TwGetLastError();
        }

回调函数是

__stdcall int MainWindow::my_callback(int nChannel, VOID *DataBuf, int width, int height, BOOL bField2, void *context, __int64 pts) {
    qDebug() << "Callback with image of " << width << "x" << height << " pixels. from channel number: "<< nChannel << " @ timestamp: " << pts;
    qDebug() << "Address: " << DataBuf << endl;
    int extra_context = *reinterpret_cast<int*>(context); // will be 42.
    return extra_context;
}

标签: callbackvideo-streamingbufferfunction-pointersvideo-capture

解决方案


此 SDK 对您的期望是定义并提供您自己的与回调类型匹配的函数:

typedef int (__stdcall *TwVideoStreamCallback)(int nChannel, VOID *DataBuf, int width, int height, BOOL bField2, void *context, __int64 pts);

__stdcall int my_callback(int nChannel, VOID *DataBuf, int width, int height, BOOL bField2, void *context, __int64 pts) {
  std::cout << "Callback with image of " << width << "x" << height << " pixels. Address: " << std::hex << DataBuf << std::endl;
  int extra_context = *reinterpret_cast<int*>(context); // will be 42.
}

int main() { // or wherever
  int extra_context = 42;
  BOOL ret = TwRegisterVideoStreamCallback(my_callback, (void*)&extra_context);
  if (!ret) {
    std::cerr << "Something went wrong" << std::endl;
  }
  SleepEx(INFINITE, false);
}

推荐阅读