1、操作流程:

2、查找并打开摄像头设备:

(1)、使用vfwcap作为输入设备:

//查找摄像头设备
//1.VFW: Video for Windows 屏幕捕捉设备。输入URL是设备的序号,从0至9。if(nullptr == (pInFmt = const_cast<AVInputFormat*>(av_find_input_format("vfwcap")))){qDebug() << "find AVInputFormat failed." << endl;break;}//打开输入设备if(avformat_open_input(&pFmtCtx, 0, pInFmt, nullptr) < 0){qDebug() << "open camera failed." << endl;break;}

(2)、使用dshow作为输入设备:

if(nullptr == (pInFmt = const_cast<AVInputFormat*>(av_find_input_format("dshow")))){qDebug() << "find AVInputFormat failed." << endl;break;}QList<QCameraInfo> cameras = QCameraInfo::availableCameras();QString urlString = QString("video=") + cameras.at(0).description();//打开输入设备if(avformat_open_input(&pFmtCtx, urlString.toStdString().c_str(), pInFmt, nullptr) < 0){qDebug() << "open camera failed." << endl;break;}

上面使用QT中的QCameraInfo类查找摄像头名称,我们还可以使用ffmpeg中的如下命令来查找:

ffmpeg -list_devices true -f dshow -i dummy

3、实现:

(1)、创建一个多线程类,在多线程类中完成视频帧的获取、解码等复杂操作:

#ifndef VIDEOTHREAD_H
#define VIDEOTHREAD_H#include <QImage>
#include <QObject>class videoThread : public QObject
{Q_OBJECT
public:explicit videoThread(QObject *parent = nullptr);signals:void sig_sendQImage(QImage);public slots:void slot_cameraVideo();
};#endif // VIDEOTHREAD_H
#include "videothread.h"
#include <QThread>
#include <QDebug>
#include <QCameraInfo>extern "C" {#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavfilter/avfilter.h"
#include "libavutil/avutil.h"
#include "libavutil/ffversion.h"
#include <libavutil/imgutils.h>
#include "libswresample/swresample.h"
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"
#include "libpostproc/postprocess.h"}videoThread::videoThread(QObject *parent) : QObject(parent)
{}void videoThread::slot_cameraVideo()
{AVFormatContext* pFmtCtx = nullptr;AVInputFormat*   pInFmt  = nullptr;int nVideoIndex          = -1;AVCodecParameters* pCodecParam = nullptr;AVCodecContext   * pCodecCtx   = nullptr;AVCodec          * pCodec    = nullptr;AVFrame* pFrame    = av_frame_alloc();AVFrame* pFrameRGB = av_frame_alloc();AVPacket* pkt = nullptr;do{//注册组件:libavdeviceavdevice_register_all();//创建设备上下文if(nullptr == (pFmtCtx = avformat_alloc_context())){qDebug() << "create AVFormatContext failed." << endl;break;}//查找摄像头设备//1.VFW: Video for Windows 屏幕捕捉设备。输入URL是设备的序号,从0至9。//2.dshow: 使用Directshow。注意作者机器上的摄像头设备名称是//“HD User Facing”,使用的时候需要改成自己电脑上摄像头设备的名称。if(1)//dshow{if(nullptr == (pInFmt = const_cast<AVInputFormat*>(av_find_input_format("dshow")))){qDebug() << "find AVInputFormat failed." << endl;break;}QList<QCameraInfo> cameras = QCameraInfo::availableCameras();QString urlString = QString("video=") + cameras.at(0).description();//打开输入设备if(avformat_open_input(&pFmtCtx, urlString.toStdString().c_str(), pInFmt, nullptr) < 0){qDebug() << "open camera failed." << endl;break;}}else //vfwcap{if(nullptr == (pInFmt = const_cast<AVInputFormat*>(av_find_input_format("vfwcap")))){qDebug() << "find AVInputFormat failed." << endl;break;}//打开输入设备if(avformat_open_input(&pFmtCtx, 0, pInFmt, nullptr) < 0){qDebug() << "open camera failed." << endl;break;}}//查找流信息if(avformat_find_stream_info(pFmtCtx, NULL) < 0){qDebug() << "cannot find stream info." << endl;break;}for(size_t i = 0;i < pFmtCtx->nb_streams;i++){if(pFmtCtx->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_VIDEO){nVideoIndex = i;break;}}if(nVideoIndex == -1){qDebug() << "cannot find video stream." << endl;break;}//查找编码器pCodecParam = pFmtCtx->streams[nVideoIndex]->codecpar;if(nullptr == (pCodec = const_cast<AVCodec*>(avcodec_find_decoder(pCodecParam->codec_id)))){qDebug() << "cannot find codec." << endl;break;}//创建编码器上下文if(nullptr == (pCodecCtx = avcodec_alloc_context3(pCodec))){qDebug() << "cannot alloc codecContext." << endl;break;}if(avcodec_parameters_to_context(pCodecCtx, pCodecParam) < 0){qDebug() << "cannot initialize codecContext." << endl;break;}//打开编码器if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0){qDebug() << "cannot open codec." << endl;break;}//设置帧数据转换上下文struct SwsContext *img_convert_ctx = nullptr;img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB24,SWS_BICUBIC, NULL, NULL, NULL);int numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);uint8_t* out_buffer = (unsigned char*)av_malloc(static_cast<unsigned long long>(numBytes) * sizeof(unsigned char));//绑定内存块if(av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize,out_buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1) < 0){qDebug() << "av_image_fill_arrays failed." << endl;break;}int ret;pkt = av_packet_alloc();av_new_packet(pkt, pCodecCtx->width * pCodecCtx->height);while(av_read_frame(pFmtCtx, pkt) >= 0){if(pkt->stream_index == nVideoIndex){if(avcodec_send_packet(pCodecCtx, pkt)>=0){while((ret = avcodec_receive_frame(pCodecCtx, pFrame)) >= 0){if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)return;else if (ret < 0) {return;}//将解码后数据转换为Rgb格式数据sws_scale(img_convert_ctx,pFrame->data, pFrame->linesize,0, pCodecCtx->height,pFrameRGB->data, pFrameRGB->linesize);//将img发送给界面进行显示QImage img(out_buffer, pCodecCtx->width, pCodecCtx->height, QImage::Format_RGB888);emit sig_sendQImage(img);QThread::msleep(10);}}av_packet_unref(pkt);}}}while(0);av_packet_free(&pkt);avcodec_close(pCodecCtx);avcodec_parameters_free(&pCodecParam);av_frame_free(&pFrame);av_frame_free(&pFrameRGB);if(pFmtCtx){avformat_close_input(&pFmtCtx);avformat_free_context(pFmtCtx);}
}

(2)多线程的创建和开启实现:

void MainWindow::createWorkThread()
{videoThread* pVideoThread = new videoThread;pVideoThread->moveToThread(&m_workThread);//线程结束后销毁videoThread对象connect(&m_workThread, &QThread::finished, pVideoThread, &QObject::deleteLater);//绑定相关信号槽connect(this, &MainWindow::sig_cameraVideo, pVideoThread, &videoThread::slot_cameraVideo);connect(pVideoThread, &videoThread::sig_sendQImage, this, &MainWindow::slot_displayImage);m_workThread.start();}void MainWindow::releaseWorkThread()
{m_workThread.quit();m_workThread.wait();
}void MainWindow::slot_displayImage(QImage img)
{ui->labDisplay->setPixmap(QPixmap::fromImage(img));
}void MainWindow::on_btnPlay_clicked()
{emit sig_cameraVideo();
}

4、简单界面显示:

ffmpeg 读取显示摄像头数据相关推荐

  1. FFmpeg读取远程摄像头视频并用opencv显示

    首先要配置好FFmpeg和opencv环境,ffpmeg可以直接读取tcp视频流数据,只需将设置好ip地址和端口即可直接打开这个数据流.然后设置好解码器, //配置静态库,也可直接添加到附加依赖项中 ...

  2. FFmpeg获取网络摄像头数据解码

    对USB摄像头实时编码,在前面已经探讨过了.这次改变下思路,尝试去截取网络摄像头的H264码流,将其解码播放. 这里的测试代码,是在海康摄像头的基础上进行的. 解码的大致流程和以前的保持一致,只不过增 ...

  3. Win10+OpenCV4.5 无法正常读取USB摄像头数据解决方案

    借鉴了这个博客. 采用OpenCV中的VideoCapture类获取USB摄像头的数据时,使用下列代码 #include "pch.h" #include "highgu ...

  4. Win10+OpenCV无法正常读取USB摄像头数据解决方案

    采用OpenCV中的VideoCapture类获取USB摄像头的数据时,使用下列代码 VideoCapture VideoStream(0);if (!VideoStream.isOpened()) ...

  5. 记录QT在实时显示摄像头数据时候切换TAB页出现异常

    最近在做一个项目,用一个TAB做页控件,里面放了不同的widget,其中Awidget是实时输出摄像头数据,是通过opencv转qimage,一开始正常,当我快速在A与B之间切换时就出现了如下错误: ...

  6. sdl2和ffmpeg显示摄像头数据

    当我们按下空格键的时候,视频可以暂停. ffmpeg 封装摄像头 extern "C" {#include <libavcodec/avcodec.h> #includ ...

  7. windows ffmpeg 推送摄像头数据到rtmp服务

    文本主要讲述windows系统下如何利用ffmpeg获取摄像机流并推送到rtmp服务,命令的用法前文 中有讲到过,这次是通过代码来实现.实现该项功能的基本流程如下: 图1 ffmpeg推流流程图 较前 ...

  8. ubuntu-Linux系统读取USB摄像头数据(uvc)

    这几天在做小车的过程中,需要用到图像采集.我想现在用的摄像头是UVC免驱的.根据国嵌的教程中有一个gspca摄像头的程序.我发现把gspca的采集程序用到uvc上时,在显示图像的时候提示没有huffm ...

  9. ROS2读取realsense摄像头数据并发布topic到ros2

    环境:ubuntu18.04, ros2 写在前面: 最近在写项目的自动化测试,需要实现先从realsense camera录制一段数据,在test case中需要以发布topic的方式播放录制的数据 ...

最新文章

  1. rtsp流+vue进行视频播放(海康威视、大华摄像头)
  2. dw网页设计期末设计一个网页_制作网站与设计网页可以用什么软件?
  3. 随机变量的分布函数-定义域问题
  4. 编译原理pl/0 c语言版 pl0.h文件
  5. 京东壕掷27亿买下一座酒店 官方回应:以办公为主!
  6. java中else语句有错_java 菜鸟 If else有错误
  7. 从一张表里选择一列加入到另一张表_将Excel多个文件汇总到一张表
  8. redis需要掌握的知识点
  9. ⭐图例结合超硬核讲解shiro⭐
  10. vscode中如何修改vetur配置_vscode vetur插件配置不换行
  11. 伟大程序员必须具备的7个好习惯
  12. html二级菜单点击淡入淡出,Web前端开发实战1:二级下拉式菜单之CSS实现
  13. ETA4322耐压30V,线性充1000mA,充电电流可调,双灯指示
  14. Boosting AdaBoost算法
  15. 文本生成 | 一篇带风格的标题生成的经典工作
  16. 2023年考研计算机数学考什么?
  17. 二维表转换为一维列表
  18. 嵌入式硬件电路设计的基本技巧
  19. CentOS7下使用ngrok搭建内网穿透服务器
  20. ‘∞‘ is not a valid numeric or approximate numeric value

热门文章

  1. 固定簇半径的分簇协议HEED matlab代码
  2. 微服务配置中心是干啥的_微服务之配置中心ConfigKeeper
  3. CSS格式化文字排版
  4. 可视化系列讲解:canvas的动画实现
  5. python Cartopy 船舶轨迹数据可视化 【GPS AIS VMS】
  6. 聚美优品、京东:为什么明知假货还有人买?
  7. xenia xbox360 忍龙2 贴图错误解决办法 与显卡太老无关 gtx760亲测
  8. 什么是地图引擎和导航引擎
  9. 【CCNA证书需要什么资格?】
  10. oppor15版本android,OPPOR15和R15梦境版区别详解