Qt打开网络摄像头~[Qt]
使用Qt打开网络摄像头,需要用到摄像头自己的API,处理函数只能在API的回调函数里面进行,需要在回调函数里面调用Widget类的部件,但是这样不行,有没有什么办法啊》求大神指导!!在VS下没问题,只需要在void CALLBACK DecCBFun1()这个回调函数里面cvShowImage(rgbimg1);就可以了,但是在Qt里面就不行~需要可提供摄像头的SDK~
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<cv.h>
#include<highgui.h>
#include<imgproc.hpp>
#include<QPixmap>
#include<QSize>
#include<dhconfigsdk.h>
#include<dhnetsdk.h>
#include<dhplay.h>
using namespace cv;
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void opencamera();
private:
Ui::Widget *ui;
//IplImage* rgbimg1;
QSize size;
//QImage qimage;
};
#endif // WIDGET_H
Widget.cpp
#include "widget.h"
#include "ui_widget.h"
#define PLAYPORT1 1
#define HEIGHT 720
#define WIDTH 1280
//全局变量
unsigned long lLogin1;
long lRealPlay1;
IplImage *rgbimg1 = cvCreateImage(cvSize(1280, 720),IPL_DEPTH_8U,3);
QImage qimage;
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
rgbimg1=NULL;
QObject::connect(ui->openCamBtn,SIGNAL(clicked()),this,SLOT(opencamera()));
}
Widget::~Widget()
{
delete ui;
}
void copy_yuvImage_to_IplImage_color(const unsigned char *input_img,IplImage* out_img)
{
IplImage *image,*yimg,*uimg,*vimg,*uuimg,*vvimg;
unsigned char *ptr_yimg,*ptr_uimg,*ptr_vimg;
int col,row;
CvSize frameSize = (WIDTH,HEIGHT);
CvSize frameSize_q = (WIDTH/2,HEIGHT/2);
image = cvCreateImage(frameSize,IPL_DEPTH_8U,3);
yimg = cvCreateImage(frameSize,IPL_DEPTH_8U,1);
uimg = cvCreateImage(frameSize_q,IPL_DEPTH_8U,1);
vimg = cvCreateImage(frameSize_q,IPL_DEPTH_8U,1);
uuimg = cvCreateImage(frameSize,IPL_DEPTH_8U,1);
vvimg = cvCreateImage(frameSize,IPL_DEPTH_8U,1);
for(row=0;row<HEIGHT;row++)
{
ptr_yimg = (unsigned char*)(yimg->imageData + row*yimg->widthStep);
for(col=0;col<WIDTH;col++)
{
*ptr_yimg++ = input_img[row*WIDTH+col];
}
}
for(row=0;row<HEIGHT/2;row++)
{
ptr_uimg = (unsigned char*)(uimg->imageData + row*uimg->widthStep);
ptr_vimg = (unsigned char*)(vimg->imageData + row*vimg->widthStep);
for(col=0;col<WIDTH/2;col++)
{
*ptr_uimg++ = input_img[HEIGHT*WIDTH + row*WIDTH/2 + col];
*ptr_vimg++ = input_img[(HEIGHT*WIDTH+HEIGHT*WIDTH/4) + row*WIDTH/2 + col ];
}
}
cvResize(uimg,uuimg,CV_INTER_LINEAR);
cvResize(vimg,vvimg,CV_INTER_LINEAR);
cvMerge(yimg,uuimg,vvimg,NULL,image);
cvCvtColor(image,out_img,CV_YCrCb2RGB);
cvReleaseImage(&image);
cvReleaseImage(&yimg);
cvReleaseImage(&vimg);
cvReleaseImage(&uimg);
cvReleaseImage(&uuimg);
cvReleaseImage(&vvimg);
}
void CALLBACK DisConnectFunc(LONG lLoginID, char *pchDVRIP, LONG nDVRPort, DWORD dwUser)
{
printf("设备断线.\n");
return;
}
void CALLBACK AutoReConnectFunc(LONG lLoginID, char *pchDVRIP, LONG nDVRPort, DWORD dwUser)
{
printf("自动重连成功.\n");
return;
}
void CALLBACK RealDataCallBackEx1(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer,DWORD dwBufSize, LONG lParam, DWORD dwUser)
{
if (dwDataType == 0) //原始视频流送播放库
{
PLAY_InputData(PLAYPORT1,pBuffer,dwBufSize);
}
}
//移走数据后,快速返回,即开始解码回调下一帧数据;不要在回调中运行长事务,否则阻塞解码下一帧数据
// pbuf里的数据是YUV I420格式的数据
void CALLBACK DecCBFun1(LONG nPort,char * pBuf,LONG nSize,FRAME_INFO * pFrameInfo, void* pUserData, LONG nReserved2)//处理视频只能在这个回调函数里面进行
{
if(pFrameInfo->nType == 3) //视频数据
copy_yuvImage_to_IplImage_color((const unsigned char *)pBuf,rgbimg1);
cvShowImage("1",rgbimg1);
//qimage = QImage((const uchar*)rgbimg1->imageData, rgbimg1->width, rgbimg1->height, QImage::Format_RGB888).rgbSwapped();//rgbSwapped()
qimage = qimage.scaled(ui->label->width(), ui->label->height(),Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//设置图片大小和label的长宽一致
// ui->label->setPixmap(QPixmap::fromImage(qimage));
// ui->label->resize(ui->label->pixmap()->size());
cvWaitKey(10);
return;
}
void Widget::opencamera()
{
//打开播放通道
PLAY_OpenStream(PLAYPORT1,0,0,1024*1024);
PLAY_SetDecCallBackEx(PLAYPORT1, DecCBFun1,NULL);
PLAY_Play(PLAYPORT1,NULL);
CLIENT_LogClose();
NET_DEVICEINFO deviceInfo ={0};
CLIENT_Init(DisConnectFunc, 0);//初始化sdk,设置断线回调函数
CLIENT_SetAutoReconnect(AutoReConnectFunc, 0);
lLogin1 = CLIENT_Login("192.168.1.109",37777,"admin","admin",&deviceInfo);//登陆设备,用户需另选设备。
if(lLogin1 != 0)
{
ui->lineEdit->setText(QString("Login Success ,Start Real Play\n"));
lRealPlay1 = CLIENT_RealPlay(lLogin1,0,0);
if(lRealPlay1 != 0)
{
//窗口句柄传空值,网络库只回调原始数据
CLIENT_SetRealDataCallBackEx(lRealPlay1, RealDataCallBackEx1, 0, 0x1f);
}
}
else
{
ui->lineEdit->setText(QString(" Login Fail \n)"));
}
//
}