0
votes

I have a mini PCI capture card (MPX-6864) which i want to use for grabbing video stream from a surveillance camera giving composite (PAL/NTSC) standard output. I have already included the DLL provided with the hardware SDK in my project. Though i am able to detect/read details about the card and device interfaced with the card through the API, I am not able to take the video stream output using the API's callback function. Please refer to the function below.

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);

My doubt is:

  1. How to call these function and acquire the data stream.
  2. How callback and callback_register functions are used in a closed API
  3. What is context pointer of callback function used in both the functions

Here is the windows SDK and driver for the particular hardware. The documentation provided in it is of not much help.

Your help will be very much appreciated.

Please refer the code below

/* 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();
        }

and the callback function is

__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;
}
1
Have you tried the obvious? (call TwRegisterVideoStreamCallback(some_function, nullptr) and see if some_function is called) the Context you pass will be passed as context to the callback. You can use it to store data that the callback needs for that stream.Botje
@Botje no i havent tried it because TwRegisterVideoCallback has an input of type TwVideoCallback so i don't know whether it will be callable or not. I am new to this concept.Rohit Kalia

1 Answers

1
votes

What this SDK expects of you is to define and provide your own function that matches the callback type:

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);
}