callback - 基于 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);
我的疑问是:
- 如何调用这些函数并获取数据流。
- 如何在封闭 API 中使用 callback 和 callback_register 函数
- 两个函数中使用的回调函数的上下文指针是什么
这是特定硬件的 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, ¶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);
}
推荐阅读
- python - 取数字列表的绝对值
- unix - ldapsearch - 将输出格式化为按用户分组
- css - 在视图/ div 边框顶部覆盖图像?
- regex - 如何获取路由路径以匹配同一正则表达式中的强制和可选字符?
- tkinter - Tkinter Labelframe 奇怪的行为:在标签中应用文本时边框颜色消失
- rust - 实现一个复杂的自定义结构序列化器
- oracle - 如果 IG 是交叉连接的结果,如何插入 - Oracle Apex
- visual-studio-code - VSCode Native 脚本 - 不识别断点
- javascript - 如何从键是单词而值是字符串长度的数组中生成对象?
- reactjs - 如何将定义为字符串的脚本标记转换为 JSX 对象?