基于 Mini PCI 的相机图像采集卡,用于在 API 中使用回调函数获取视频流数据
Mini PCI based camera frame grabber for acquisition of video stream data using a callback function in API
我有一个迷你 PCI 采集卡 (MPX-6864),我想用它从监控摄像头抓取视频流,提供复合 (PAL/NTSC) 标准输出。
我已经在我的项目中包含了硬件SDK提供的DLL。虽然我可以 detect/read 通过 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);
我的疑问是:
- 如何调用这些函数并获取数据流。
- 如何在封闭的 API
中使用回调和 callback_register 函数
- 两个函数中使用的回调函数的上下文指针是什么
非常感谢您的帮助。
请参考以下代码
/* 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, ¶Value);
// int width = paraValue;
qDebug() << "Video Width: " << paraValue;
TwGetVideoPara(chHandle, vpHeight, ¶Value);
// int height = paraValue;
qDebug() << "Video Height: " << paraValue;
TwGetVideoPara(chHandle, vpFrameRate, ¶Value);
qDebug() << "Video Frame Rate: " << paraValue;
TwGetVideoPara(chHandle, vpPixelFormat, ¶Value);
qDebug() << "Video PIXEL Format: " << paraValue;
TwGetVideoPara(chHandle, vpStandard, ¶Value);
qDebug() << "Video Video Standard: " << paraValue;
TwGetVideoPara(chHandle, vpBufferType, ¶Value);
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;
}
本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);
}
我有一个迷你 PCI 采集卡 (MPX-6864),我想用它从监控摄像头抓取视频流,提供复合 (PAL/NTSC) 标准输出。 我已经在我的项目中包含了硬件SDK提供的DLL。虽然我可以 detect/read 通过 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);
我的疑问是:
- 如何调用这些函数并获取数据流。
- 如何在封闭的 API 中使用回调和 callback_register 函数
- 两个函数中使用的回调函数的上下文指针是什么
非常感谢您的帮助。
请参考以下代码
/* 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, ¶Value);
// int width = paraValue;
qDebug() << "Video Width: " << paraValue;
TwGetVideoPara(chHandle, vpHeight, ¶Value);
// int height = paraValue;
qDebug() << "Video Height: " << paraValue;
TwGetVideoPara(chHandle, vpFrameRate, ¶Value);
qDebug() << "Video Frame Rate: " << paraValue;
TwGetVideoPara(chHandle, vpPixelFormat, ¶Value);
qDebug() << "Video PIXEL Format: " << paraValue;
TwGetVideoPara(chHandle, vpStandard, ¶Value);
qDebug() << "Video Video Standard: " << paraValue;
TwGetVideoPara(chHandle, vpBufferType, ¶Value);
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;
}
本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);
}