DecodeVedio.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #ifndef DECODEVEDIO_H
  2. #define DECODEVEDIO_H
  3. #include <QObject>
  4. #include <QQueue>
  5. #include <QTimer>
  6. #include <QMutex>
  7. #include <QWaitCondition>
  8. #include <QImage>
  9. #include "RingQueue/RingQueue.hpp"
  10. // #include "threadcontroller.h"
  11. extern "C"
  12. {
  13. // #include <libavcodec/avcodec.h>
  14. #include <libavformat/avformat.h>
  15. // #include <libswscale/swscale.h>
  16. // #include <libavutil/imgutils.h>
  17. }
  18. /**
  19. * 使用方式:
  20. * 1. 初始化FFmpeg:initFFmpeg()
  21. * 2. 开启解码线程:startDecodeVedio()
  22. * 3. 获取一帧图像:getOneImage()
  23. * 4. 停止解码线程:stopDecodeVedio()
  24. * 5. 在初始化完成后,未进入第二步的之前,可以获取视频的宽高信息,也可以设置宽高信息
  25. *
  26. */
  27. class DecodeVedio : public QObject
  28. {
  29. Q_OBJECT
  30. public:
  31. explicit DecodeVedio(QThread* thread, QObject* parent = nullptr);
  32. ~DecodeVedio();
  33. /* 获取硬件解码器 */
  34. void getHWDecoder();
  35. // void setFileName(const QString& fileName) { m_fileName = fileName; }
  36. /* 初始化函数 */
  37. void initFFmpeg(const QString& fileName);
  38. /* 取消ffmpeg初始化函数 */
  39. void unInitFFmpeg();
  40. /* 获取ffmpeg初始化状态 */
  41. bool isInitFFmpeg() { return m_initFFmpeg; }
  42. /* 开始解码视频,开始前先设置视频名称 */
  43. void startDecodeVedio();
  44. /* 停止解码视频,也是停止线程 */
  45. void stopDecodeVedio();
  46. /* 设置当前播放位置 */
  47. void setCurrentPos(quint64 pos);
  48. /* 获取当前播放位置 */
  49. qint64 getCurrentPos();
  50. /* 获取视频时长 */
  51. qint64 getDuration();
  52. /* 获取解码线程是否运行 */
  53. bool isRunning() { return m_isRunning; }
  54. /* 唤醒队列非空条件变量 */
  55. void wakeUpCondQueueNoEmpty();
  56. /* 获取一帧图像 */
  57. QImage* getOneImage();
  58. /* 获取一帧图像,直到有图像为止 */
  59. QImage* getOneImageUntilHave();
  60. /* 获取帧数 */
  61. int getFrameCount();
  62. /* 获取图像宽度 */
  63. int getSrcVideoWidth() const {return m_srcWidth;}
  64. /* 获取图像高度 */
  65. int getSrcVideoHeight() const {return m_srcHeight;}
  66. /* 设置图像宽度和高度 */
  67. void setVideoSize(int width,int height);
  68. signals:
  69. void signal_oneImage(); /* 一帧图像信号 */
  70. void signal_playCompleted(); /* 播放完成信号 */
  71. private:
  72. void freeFFmpeg(); /* 取消ffmpeg初始化函数 */
  73. void decodeVedio(); /* 解码视频的工作函数,这个就是新线程 */
  74. void decodeUsingCPU(); /* 软解码线程 */
  75. void exitThread(); /* 退出线程 */
  76. void pauseDecode(); /* 暂停解码 */
  77. qreal rationalToDouble(AVRational* rational); /* 将AVRational转换为double */
  78. void freeAll(); /* 释放所有资源 */
  79. private slots:
  80. void do_startDecodeVedio(); /* 开启解码 */
  81. private:
  82. QThread* m_thread = nullptr; /* 解码线程 */
  83. std::atomic_bool m_isRunning = false; /* 解码线程是否运行 */
  84. QTimer m_startThread; /* 开启线程的定时器 */
  85. std::atomic_bool m_initFFmpeg = false; /* ffmpeg初始化标志 */
  86. std::atomic_bool m_threadStopped = false; /* 停止线程 */
  87. std::atomic_bool m_pauseDecode = false; /* 暂停解码 */
  88. std::atomic_bool m_decodeStatus = false; /* 解码状态,这里主要是检测是否暂停解码 */
  89. std::atomic_bool m_isSeek = false; /* 是否跳转 */
  90. QString m_fileName; /* 解码的视频文件名称 */
  91. AVFormatContext *m_pFormatContext = nullptr; /* 格式上下文,贯穿全局 */
  92. AVCodecContext *m_pCodecCtx = nullptr; /* 解码器上下文 */
  93. AVPacket* m_packet = nullptr; /* 存储解码前的数据,一个数据包 */
  94. AVFrame* m_pFrame = nullptr; /* 存储解码后的一帧数据原始视频编码 */
  95. AVFrame* m_pFrameRGB = nullptr; /* 存储解码后的一帧数据,RGB格式 */
  96. AVFrame* m_pFrameHW = nullptr; /* 存储解码后的一帧数据,硬件解码 */
  97. struct SwsContext *m_sws_ctx = nullptr; /* 视频转换上下文 */
  98. uint8_t *m_buffer = nullptr; /* 存储解码后的一帧数据,RGB格式 */
  99. int m_videoStream = -1; /* 记录视频流是第几个流 */
  100. int m_srcWidth = 0; /* 图片原本宽度 */
  101. int m_srcHeight = 0; /* 图片原本高度 */
  102. int m_width = 0; /* 图像宽度 */
  103. int m_height = 0; /* 图像高度 */
  104. int m_totalFrame = 0; /* 视频总帧数 */
  105. int m_fps; /* 每秒的帧数 */
  106. quint64 m_currentFrame = 0; /* 当前已播放的帧数 */
  107. quint64 m_pts = 0; /* 当前帧显示时间 */
  108. qint64 m_duration = 0; /* 视频时长 */
  109. qint64 m_currentPos = 0; /* 当前播放位置 */
  110. qint64 m_startPos = 0; /* 起始位置,后续操作都需要在这各基础上操作 */
  111. // QImage *m_image = nullptr;
  112. int m_queueMaxNum = 10; /* 这里不是环形队列,最大设置为30帧图像 */
  113. QQueue<QImage*> m_queueImage; /* 视频帧队列 */
  114. QMutex m_mutexQueue; /* 队列互斥锁 */
  115. QWaitCondition m_condQueueNoFull; /* 队列不满,可以入队 */
  116. QWaitCondition m_condQueueNoEmpty; /* 队列非空,可以读取 */
  117. QList<int> m_listHWDeviceType; /* 保存当前环境支持的硬件解码器 */
  118. AVBufferRef* m_hw_device_ctx = nullptr; /* 对数据缓冲区的引用 */
  119. RingQueue<QImage*> m_ringQueue; /* 环形队列,存储生成的图像 */
  120. };
  121. #endif /* DECODEVEDIO_H */