修改opencv3.4 VideoCapture dshow模块以支持圆刚cv710等需要配置CrossBar的采集卡

时间:2021-03-23 03:33:46

Opencv缺省的VideoCapture模块对于一些需要配置crossbar的采集卡支持不好,无法配置或者配置后视频格式不对,需要对其函数功能进行补充和修正。以圆刚cv710卡为例:

该卡hdmi采集要正常工作需要配置crossbar如下图的属性

修改opencv3.4 VideoCapture dshow模块以支持圆刚cv710等需要配置CrossBar的采集卡

对opencv要做以下修改

1,增加crossbar的属性配置项

在videoio.hpp 中增加配置crossbar Input 属性,正好看到空了个31,先用上,当然加在最后也行。

       CAP_PROP_ISO_SPEED     =30,
       CAP_CROSSBAR_INPIN_TYPE = 31, //!< Add CrossBar Setting For some kind of videocard by whm

       CAP_PROP_BACKLIGHT     =32,

2,增加对crossbar input pin 类型的支持

修改 cap_dshow.cpp中的setPhyCon, 原本该函数只支持前4种类型的 PhysicalConnectorType enumeration, 新增加

PhysConn_Video_YRYBY和PhysConn_Video_SerialDigital,刚的cv710 hdmi采集就用到SerialDigital类型作为input pin.

void videoInput::setPhyCon(int id, int conn){

    switch(conn){

        case 0:
            VDList[id]->connection = PhysConn_Video_Composite;
            break;
        case 1:
            VDList[id]->connection = PhysConn_Video_SVideo;
            break;
        case 2:
            VDList[id]->connection = PhysConn_Video_Tuner;
            break;
        case 3:
            VDList[id]->connection = PhysConn_Video_USB;
            break;
        case 4:
            VDList[id]->connection = PhysConn_Video_1394;
            break;
case 5:
    VDList[id]->connection = PhysConn_Video_YRYBY;
    break;
case 6:
           VDList[id]->connection = PhysConn_Video_SerialDigital;
   break;

        default:
            return; //if it is not these types don't set crossbar
        break;
    }

    VDList[id]->storeConn    = conn;
    VDList[id]->useCrossbar    = true;
}

然后修改

bool VideoCapture_DShow::setProperty(int propIdx, double propVal) 函数

对设置的CAP_CROSSBAR_INPIN_TYPE 响应

增加部分如下

case CAP_CROSSBAR_INPIN_TYPE:
 
if (cvFloor(propVal) < 0)
break;
g_VI.stopDevice(m_index);
g_VI.setupDevice(m_index,  cvFloor(propVal));

break;

该部分函数会调用前面修改的setPhyCon函数设置crossbar的contype并enable crossbar选项,然后关闭dshow control 重建调用其

int videoInput::start(int deviceID, videoDevice *VD) 函数初始化采集

可以看到这里函数这里原有的

  if(VD->useCrossbar)
    {
        DebugPrintOut("SETUP: Checking crossbar\n");
        routeCrossbar(&VD->pCaptureGraph, &VD->pVideoInputFilter, VD->connection, CAPTURE_MODE);

    }

部分将被激活并调用routeCrossbar选择匹配的input pin并连接找到的PhysConn_Video_VideoDecoder类型output PIN并自动连接,这样就设置好了采集卡的crossbar.

最后,需要修改

static bool setSizeAndSubtype(videoDevice * VD, int attemptWidth, int attemptHeight, GUID mediatype){

    VIDEOINFOHEADER *pVih =  reinterpret_cast<VIDEOINFOHEADER*>(VD->pAmMediaType->pbFormat); 这个函数,原来的函数有个问题会导致采集卡找不到可以工作的匹配MediaFormat.请注意新增的红色部分

    //set new size:
    //width and height
    HEADER(pVih)->biWidth  = attemptWidth;
    HEADER(pVih)->biHeight = attemptHeight;
//set new src/dst rect
pVih->rcSource.top = pVih->rcSource.left = pVih->rcTarget.top =pVih->rcTarget.left=0;
pVih->rcSource.right = pVih->rcTarget.right= attemptWidth;
pVih->rcSource.bottom = pVih->rcTarget.bottom = attemptHeight;

原来的代码没有这一块设置,在圆刚cv710上的表现就是仍然使用缺省原有的640x480 rcSource和rcTarget,结果是 hr = VD->streamConf->SetFormat(VD->pAmMediaType); 一直失败导致无法找到合适的MediaType. 所以需要新增这段代码以使mediatype结构数据匹配。

所有部分修改完毕后编译opensource替换原有lib和dll.测试下新的模块,发现已经可以连接自己的cv710了,代码中设置CAP_CROSSBAR_INPIN_TYPE 参数为6,正是PhysConn_Video_SerialDigital的值

c++测试部分代码:

void CcvtestDlg::OnBnClickedButton1()
{
// TODO:  在此添加控件通知处理程序代码
VideoCapture cap(0);
cap.set(CAP_PROP_FRAME_WIDTH, 1920);
cap.set(CAP_PROP_FRAME_HEIGHT, 1080);

cap.set(CAP_CROSSBAR_INPIN_TYPE , 6);

Mat img;
namedWindow("test", WINDOW_NORMAL);
resizeWindow("test", 960, 640);
while (1)
{
if (cap.read(img))
{
imshow("test", img);
if ('q' ==waitKey(1))
break;
}
}
destroyAllWindows();
cap.release();
}

Python3测试代码

import cv2
print("test cv")
cap=cv2.VideoCapture(0)
cap.set(5,60)
cap.set(3,1920)
cap.set(4,1080)
cap.set(31,6)


ret,img=cap.read()
cv2.namedWindow("cap",cv2.WINDOW_NORMAL)
cv2.resizeWindow("cap",960,640);
while True:
    ret,img=cap.read()
    if ret==False:
        continue
    cv2.imshow("cap",img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()

cv2.destroyAllWindows()

然后就可以愉快的进行opencv video其他的工作了!

修改opencv3.4 VideoCapture dshow模块以支持圆刚cv710等需要配置CrossBar的采集卡