若该文为原创文章,未经容许不得转载
原博主博客地址: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