若该文为原创文章,未经容许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/108416332
红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中…(点击传送门)

Qt开发专栏:我的项目实战(点击传送门)

Qt开发专栏:三方库开发技术


需要

  关上检测摄像头工具,包含分辨率和帧率。


Demo

  

  

体验下载地址

  CSDN:https://download.csdn.net/download/qq21497936/12815691
  QQ群:1047134658(点击“文件”搜寻“ffmpegCameraTool”,群内与博文同步更新)


波及其余技术

  QCameraInfo关上摄像头偶然拿不到摄像头;
  QCamera动静切换分辨率会导致解体;
  QCamera解决高分辨率存在卡顿问题;
  OpenCV无奈拿取摄像头;
  OpenCV设置高分辨率存在帧率跟不上,卡顿问题;
  OpenCV保留高分辨率视频须要批改源码,否则限度mat下限大小为0xFFFF;
  OpenCV保留高分辨率批改源码后存储视频会导致通道凌乱,须要手动改正色彩通道。


v1.0.0性能

  • 程序启动关上计算机默认第一个摄像头,最高分辨率最高帧率关上;
  • 反对动静切换分辨率和帧率;
  • 反对原图显示,等比例显示;
  • 多个设施终端测试可用;


本文章博客地址:https://blog.csdn.net/qq21497936/article/details/108416332

外围代码

FfmpegCameraManager.h

#ifndef FFMPEGCAMERAMANAGER_H#define FFMPEGCAMERAMANAGER_H/************************************************************\ * 控件名称: FfmpegCameraManager, ffmpeg治理类(用于摄像头操作) * 控件形容: *          1.关上摄像头 *          2.反对动静切换分辨率 * 作者:红模拟    联系方式:QQ21497936 * 博客地址:https://blog.csdn.net/qq21497936 *       日期                版本               形容 *    2018年09年14日     v1.0.0         ffmpeg模块封装空类 *    2020年09年05日     v1.1.0         ffmpeg关上摄像头,反对的动静分辨率切换\************************************************************/#include <QObject>#include <QString>#include <QDebug>#include <QTimer>#include <QThread>#include <QImage>#include <QProcess>#include <QMessageBox>extern "C" {    #include "libavcodec/avcodec.h"    #include "libavformat/avformat.h"    #include "libswscale/swscale.h"    #include "libavdevice/avdevice.h"    #include "libavformat/version.h"    #include "libavutil/time.h"    #include "libavutil/mathematics.h"    #include "libavformat/avformat.h"    #include "libswscale/swscale.h"    #include "libswresample/swresample.h"    #include "errno.h"    #include "error.h"}#define LOG qDebug()<<__FILE__<<__LINE__class FfmpegCameraManager : public QObject{    Q_OBJECTpublic:public:    explicit FfmpegCameraManager(QObject *parent = nullptr);signals:    void signal_captureOneFrame(QImage image);public:    static QString getAvcodecConfiguration();public:    bool init();    bool openUsbCamera();    QString getUsbCameraName();    QList<QString> getUsbCameraInfo();public slots:    void slot_start();    void slot_stop();    void slot_setSizeFps(int index);protected slots:    void slot_captureOneFrame();signals:public slots:private:    static bool _init;    AVFormatContext *_pAVFormatContext;         // 全局上下文    AVInputFormat *_pAVInputFormat;    AVDictionary* _pAVDictionary;               // 关上编码器的配置    AVCodecContext *_pAVCodecContextForAudio;   // 音频解码器上下文    AVCodecContext *_pAVCodecContextForVideo;   // 视频解码器上下文(不带音频)    AVCodec * _pAVCodecForAudio;                // 音频解码器    AVCodec * _pAVCodecForVideo;                // 视频解码器(不带音频)    int _streamIndexForAudio;                   // 音频流序号    int _streamIndexForVideo;                   // 视频流序号    SwrContext *_pSwrContextForAudio;           // 音频转换上下文    bool _running;    bool _first;    bool _opened;    uint8_t *_pOutBuffer;    AVFrame * _pFrame;    AVFrame * _pFrameRGB;    AVPacket *_pAVPacket;    SwsContext *_pSwsContext;    int _videoIndex;    QString _cameraDescription;    QList<QSize> _listSize;    QList<int> _listFps;    QList<QString> _listSizeFpsInfo;    int _currentSuzeFpsIndex;};#endif // FfmpegCameraManager_H

FfmpegCameraManager.cpp

...void FfmpegCameraManager::slot_captureOneFrame(){    if(_first)    {        // 读取一个媒体文件的数据包以获取流信息        if(avformat_find_stream_info(_pAVFormatContext, NULL) < 0)        {            LOG << "Couldn't find stream information";        }else{            LOG << "Success find stream information";        }        // 循环查找数据包蕴含的流信息,直到找到视频类型的流        //  便将其记录下来 保留到videoStream变量中        _videoIndex = -1;        for(int index = 0; index < _pAVFormatContext->nb_streams; index++)        {            if(_pAVFormatContext->streams[index]->codec->codec_type == AVMEDIA_TYPE_VIDEO)            {                _videoIndex = index;                break;            }        }        if(_videoIndex == -1)        {            LOG << "Couldn't find a video stream";        }else{            LOG << "Success find a video stream";        }        _pAVCodecContextForVideo = _pAVFormatContext->streams[_videoIndex]->codec;        _pAVCodecForVideo = avcodec_find_decoder(_pAVCodecContextForVideo->codec_id);        //软编码//       _pAVCodecForVideo = avcodec_find_encoder(AV_CODEC_ID_H264);        //硬编码//       _pAVCodecForVideo = avcodec_find_encoder_by_name("nvenc_h264");        if(_pAVCodecForVideo == NULL)        {            qDebug() << ("Codec not found.\n");        }else{            qDebug() << "Codec found Successfuly!\n";        }        if(avcodec_open2(_pAVCodecContextForVideo, _pAVCodecForVideo, NULL) < 0)//关上解码器        {            LOG << "Failed to  open codec";        }else{            LOG << "Success open codec";        }        //调配一个AVFrame并将其字段设置为默认值        if(_pFrame == 0)        {            _pFrame = av_frame_alloc();        }        if(_pFrameRGB == 0)        {            _pFrameRGB = av_frame_alloc();        }        //调配和返回一个SwsContext你须要它来执行应用swsscale()的缩放/转换操作        _pSwsContext = sws_getContext(_pAVCodecContextForVideo->width,                                      _pAVCodecContextForVideo->height,                                      _pAVCodecContextForVideo->pix_fmt,                                      _pAVCodecContextForVideo->width,                                      _pAVCodecContextForVideo->height,                                      AV_PIX_FMT_RGB32,                                      SWS_BICUBIC,                                      NULL,                                      NULL,                                      NULL);        int numBytes = avpicture_get_size(AV_PIX_FMT_RGB32,                                          _pAVCodecContextForVideo->width,                                          _pAVCodecContextForVideo->height);        LOG << "numBytes:" << numBytes;        _pOutBuffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));        avpicture_fill((AVPicture *)_pFrameRGB,                       _pOutBuffer,                       AV_PIX_FMT_RGB32,                       _pAVCodecContextForVideo->width,                       _pAVCodecContextForVideo->height);//依据指定的图像参数和提供的图像数据缓冲区设置图像域        int ySize = _pAVCodecContextForVideo->width * _pAVCodecContextForVideo->height;        LOG;        //调配一个packet        if(_pAVPacket == 0)        {            LOG;            _pAVPacket = (AVPacket *)malloc(sizeof(AVPacket));            //调配packet的数据            av_new_packet(_pAVPacket, ySize);        }else{            LOG;            av_free_packet(_pAVPacket);            av_new_packet(_pAVPacket, ySize);            LOG;        }        _first = false;    }    // 解码压缩    if(av_read_frame(_pAVFormatContext, _pAVPacket) < 0)    {        LOG << "解码失败";        return;    }    if(_pAVPacket->stream_index == _videoIndex)    {        int gotPicture;        // 解码一帧视频数据        int ret = avcodec_decode_video2(_pAVCodecContextForVideo, _pFrame, &gotPicture, _pAVPacket);        if(ret < 0)        {            LOG << "decode error";        }        if(gotPicture)        {            // 缩放图像切片,并将失去的缩放切片放在pFrameRGB->data图像中            sws_scale(_pSwsContext,                      (uint8_t const * const *)_pFrame->data,                      _pFrame->linesize,                      0,                      _pAVCodecContextForVideo->height,                      _pFrameRGB->data,                      _pFrameRGB->linesize);            QImage tmpImg((uchar *)_pOutBuffer,                          _pAVCodecContextForVideo->width,                          _pAVCodecContextForVideo->height,                           QImage::Format_RGB32);            QImage image = tmpImg.copy();            LOG << "get a pciture";            emit signal_captureOneFrame(image);            QTimer::singleShot(10, this, SLOT(slot_captureOneFrame()));        }    }}...


原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/108416332