Qt + FFmpeg 屏幕录制器

发布时间:2024-10-03 13:01

一、环境搭建

可以看我的另一篇文章 《Qt + FFmpeg 视频播放器》 , 在这里就不再重复了。
PS:一定要确认好FFmpeg库的版本,我在使用的时候因为函数接口对不上,头发掉了不少…所以,一定要慎重啊!!!

二、实战演练

1 . 功能介绍

源码链接 : https://github.com/AutoCatFuuuu/QT/tree/master/gdigrab

  1. 可以录制屏幕 录制系统摄像头 并显示出来
  2. 保存录制文件

实际效果图

这里展示的是录制桌面后保存下来的小视频【很小很小】

\"Qt

2 . 编码流程图

\"Qt

关键代码 【都是关键 这里对封装的类进行简单说明 程序内也有详细注释】

aencode.h

【AEncode】对编码进行封装
功能说明:

  1. 本demo工程里是实现录取屏幕 视频数据是从gdigrab里抓过来的
  2. 想实现 本地文件视频转码 可以先把视频解码出来再传到encodecOneFrame()

注意:

  1. 成员函数声明顺序就是编码流程的顺序,请一定要按顺序执行,否则程序会崩溃
  2. 本程序目前只支持 单视频流编码
  3. 编码格式会根据输出文件名猜测判断
  4. 对于编码器的参数设置接口并没有写很多 主要是因为对编码器的参数没啥研究…
  5. setPixFormat() 别乱设置 编码器不支持的话,会没法编码的
    默认是 AV_PIX_FMT_YUV420P
  6. setSize() 默认是 w:1920 h:1080
  7. setFPS() 默认 25
#ifndef AENCODE_H
#define AENCODE_H

#ifdef __cplusplus
extern \"C\"{
#include 
#include 
#include 
#include 
}
#endif

class AEncode
{
public:
    AEncode();                              //初始化私有成员
    ~AEncode();                             //调用free();
    void setPath(char* path);               //设置文件路径
    void setSize(int width,int height);     //设置视频宽高
    void setFPS(int value) { fps = value; } //设置帧率
    void setPixFormat(AVPixelFormat p) { VPixFormat = p; }
                                            //设置输出图像的颜色空间
    void setSwsCtx(AVPixelFormat src, int src_w, int src_h);
                                            //设置转换格式
    bool initOutFile();                     //为输出文件初始化
    bool initVideo();                       //初始化视频编码器
    bool startEncodec();                    //写文件头
    bool encodecOneFrame(AVFrame *frame, int index);
                                            //编码一帧
    bool endEncodec();                      //写文件尾
    void free();                            //销毁资源

private:
    AVFormatContext     *pFormatCtx;        //多媒体上下文
    AVCodecContext      *pVCodecCtx;        //视频编码器上下文
    AVCodec             *pVCodec;           //视频编码器
    AVOutputFormat      *fmt;               //输出参数
    AVStream            *pVStream;          //视频输出流
    AVFrame             *pVFrame;           //视频编码帧
    AVPacket            *pVPacket;          //视频编码帧
    AVPixelFormat       VPixFormat;         //图像的颜色空间
    struct SwsContext   *pSwsCtx;           //转换格式
    unsigned char       *out_buffer;        //图像缓存区
    char                path[256];          //文件路径
    int                 width;              //宽
    int                 height;             //高
    int                 fps;                //帧率
    int                 videoindex;         //视频流
};

#endif // AENCODE_H

gdigrab.h

【Gdigrab】对抓取桌面进行封装

#ifndef GDIGRAB_H
#define GDIGRAB_H

#ifdef __cplusplus
extern \"C\"{
#include 
#include 
#include 
#include 
#include 
#include 
}
#endif

#include \"aencode.h\"

class Gdigrab {
public:
    Gdigrab();
    ~Gdigrab();

    bool open();    //打开
    bool read();    //读取
    void setOptions(int x,int y,int width,int height);
    int getFPS() { return fps.num; }            //获取帧率
    AVFrame* getFrame() { return pFrameRGB; }   //获取图像
    void stop();    //停止编码并关闭文件

private:
    AVDictionary        *options;       //参数
    AVFormatContext     *pFormatCtx;    //文件内容信息 这里指屏幕
    AVCodecContext      *pCodecCtx;     //解码器上下文
    AVCodec             *pCodec;        //解码器
    AVFrame             *pFrame;        //解码出来的图像
    AVFrame             *pFrameRGB;     //转换成RGB的图像
    AVPacket            *packet;        //图像解码前的包
    AVRational          fps;
    unsigned char       *out_buffer;    //图像缓存区
    struct SwsContext   *pSwsContext;   //转换格式
    int                 videoindex;     //视频流索引

    AEncode E;  //编码器

};

#endif

3 . 写在最后

	本作品依然是兴趣使然的产物,适合初学者入门使用,本人对于编码这种东西真的是零概念的,以至于查找
资料的时候真的是痛不欲生。【官网的例子用的是很早的版本,雷博士的例子是从本地文件里读取的】 自己选的
坑,哭着也要把它填完。总之,在花费两个星期的时间 , Demo 也写烂几个 把这玩意做出来了。关于代码里有
啥疑惑的可以留言【佛系回复】或者 联系本人QQ :673315140  (ˉ▽ˉ;)...

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号