不用 SDL 的QT+FFMPEG 播放器

发布于 2022-09-09 20:07:52 字数 9224 浏览 26 评论 1

QT+ffmpeg
1、不用SDL的理由
   SDL是为游戏开发的,大量的依赖硬件加速。不用sdl是为了能方便的将程序移植到其他的平台 。
   本人受条件限制未向其他系统移植。但由于没采用QT(ffmpeg)之外的其他第三方代码,相信
   移植是个很小的问题。本人曾经做过arm920+qt+linux(fambuffer)的开发。
   本程序仅用了Qwideg来显示,就是为了移植方便。ffmpeg用C写的可以向多种平台移植。
2、如何实现音频视频同步
    本范例采用系统时钟作为主时钟,用音频时钟校正主时钟。
3、如何实现多趋缓冲
    本范例采用多线程处理机制。
    1、QFfmpeg :主要负责读取数据包,存入QList列表.压缩前的数据占用空间小。缓冲大小可设,按视频帧数和声卡缓冲大小决定
    2、QAudioThread:音频解码
    3、QVideoThread:视频解码
    4、QFfPlay :播放 (没有用定时器,定时器误差太大)
4、本范例实现QT+ffmpeg播放器的基本功能,仅出于爱好开发,未进行系统排错,用于大家参考交流。
    在开发期间参考了ffplay 。
  5、实现在QT4.6 QT4.7forwindows版编译运行,内存无重大泄露。

  1. #ifndef QFFMPEG_H
  2. #define QFFMPEG_H
  3. #include <QThreadPool>
  4. #include <QRunnable>
  5. #include <QWidget>
  6. #include <QAudioDeviceInfo>
  7. #include <QAudioOutput>
  8. #include <QAudioFormat>
  9. #include <QThread>
  10. #include <QImage>
  11. #include <QMutex>
  12. #include <QTime>
  13. #include <QPainter>
  14. #include <QIODevice>
  15. #include <QWaitCondition>
  16. #include <QSemaphore>
  17. #include <QReadWriteLock>
  18. #include <QDebug>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <memory.h>//注意要包含此头文件与qDebug函数相关
  22. #include <stdint.h>
  23. #include <QList>
  24. extern "C"
  25. {
  26. //ffmpeg相关的头文件
  27. #include <libavcodec/avcodec.h>
  28. #include <libavutil/common.h>
  29. #include <libavutil/avstring.h>
  30. #include <libavcodec/avcodec.h>
  31. #include <libavformat/avformat.h>
  32. #include <libswscale/swscale.h>
  33. #include <libavcodec/opt.h>
  34. #include <libavformat/avio.h>
  35. //#include <libavdevice/avdevice.h>
  36. }
  37. //播放信息
  38. #define DEFAULT_IMAGEFMT QImage::Format_RGB32
  39. #define DEFAULT_FRAMEFMT PIX_FMT_RGB32
  40. #define MAX_AUDIO_DIFFTIME 1000000  //音频时间差,最大值
  41. #define AUDIOBUFFERSIZE (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2 //音频缓冲大小
  42. #define MAX_BUFFER 50
  43. class QMasterClock //主时钟
  44. {
  45. public:
  46.     QMasterClock();
  47.     void adjusttime(int us);
  48.     qint64 getuscurtime();
  49.     void setstarttime(QTime t);
  50. protected:
  51.     QReadWriteLock m;
  52.     QTime starttime;
  53. };
  54. class QDecodecThread : public QThread
  55. {
  56.     Q_OBJECT
  57. public:
  58.     QDecodecThread(AVFormatContext *f,AVCodecContext *c,QMasterClock *cl,int index,QObject *parent=0);
  59.     ~QDecodecThread();
  60.     void run()=0;
  61.     void setstreamindex(const int index);
  62.     int getstreamindex() ;
  63.     int getusdtime() ;
  64.     void setusdtime(int dt);
  65.     void setisend(const bool b);
  66.     void lockdata();
  67.     void unlockdata();
  68.     int getcount() ;
  69.     void putpacket(AVPacket *p);
  70.     void free_packet(AVPacket *p);
  71.     AVPacket* getpacket();
  72.     qint64 getus(qint64 t);
  73.     QSemaphore sempfree;
  74. protected:
  75.     AVCodecContext *actx; //解码器
  76.     AVFormatContext  *formatctx;
  77.     int stream_index;
  78.     QMasterClock *masterclock;
  79.     QSemaphore semp;
  80.     bool isend;
  81.     QList <AVPacket*> pkts;
  82.     int usdtime;//时间差值,用于修正主时钟
  83.     QMutex mutex;
  84.     qint64 basetime;
  85. };
  86. class QAudioThread : public QDecodecThread
  87. {
  88.     Q_OBJECT
  89. public:
  90.     QAudioThread(AVFormatContext *f,AVCodecContext *c,QMasterClock *cl,int index,QObject *parent=0);
  91.     ~QAudioThread();
  92.     QAudioOutput* getaudio();
  93.     void run();
  94.     void play();
  95.     int ffsampleratetoint(const SampleFormat sf);
  96.     qint64 caltime(const uint64_t pts);
  97. public slots:
  98.   void notified();
  99.   void audiostate(QAudio::State state);
  100. protected:
  101.    int writeaudio(char *data ,const int size);
  102.     QAudioOutput *audio;
  103.     QIODevice *audioIO;
  104. };
  105. class QVideoThread : public QDecodecThread
  106. {
  107.    Q_OBJECT
  108. public:
  109.    QVideoThread(AVFormatContext *f, AVCodecContext *c,QMasterClock *cl,int index,QObject *parent=0);
  110.    ~QVideoThread();
  111.    qint64 getframebuffer(char *data);
  112.    int getwidth() const;
  113.    int getheight() const;
  114.    int getframesize();
  115.    void run();
  116. protected:
  117.    SwsContext *m_img_convert_ctx;//图像转换设置
  118.    char *framebuffer;
  119.    int framebuffersize;
  120.    qint64 pts;
  121.    QWaitCondition videowait;
  122. private:
  123.    AVFrame *yuvframe;
  124.    AVFrame *rgbframe;
  125. };
  126. class QSubtitleThread : public QDecodecThread
  127. {
  128.     Q_OBJECT
  129. public:
  130.     QSubtitleThread(AVFormatContext *f,AVCodecContext *c,QMasterClock *cl,int index,QObject *parent=0)
  131.         :QDecodecThread(f,c,cl,index,parent)
  132.     {}
  133.     void run(){}
  134. };
  135. class QFfWidget : public QWidget
  136. {
  137.     Q_OBJECT
  138. public:
  139.     explicit QFfWidget(QWidget *parent = 0);
  140.     ~QFfWidget();
  141.     void setframe(QImage *f);
  142.     void lockframe();
  143.     void unlockframe();
  144. private:
  145.     QImage *frame;
  146.     QMutex m;
  147. protected:
  148.     void paintEvent(QPaintEvent *);
  149. };
  150. class QFfplay : public QThread
  151. {
  152.     Q_OBJECT
  153. public:
  154.     QFfplay(QVideoThread *v,QMasterClock *c, QObject *parent);
  155.     ~QFfplay();
  156.     QWidget* getwidget();
  157. protected:
  158.     void run();
  159.     QVideoThread *video;
  160.     QMasterClock *masterclock;
  161.     QImage *frame;
  162.     char *framebuffer;
  163.     QFfWidget *widget;
  164. };
  165. class QFfmpeg : public QThread
  166. {
  167.     Q_OBJECT
  168. public:
  169.     explicit QFfmpeg(QObject *parent);
  170.     //设置参数
  171.     void seturl(QString url);
  172.     bool open();
  173.     void close();
  174.     bool play();
  175.     void stop();
  176.     //判断视频是否结束
  177.     bool atEnd();
  178.     bool IsOpen();
  179.     QWidget* getwidget();
  180. signals:
  181. public slots:
  182. protected:
  183.     void run();
  184. private:
  185.     /****解码相关******************/
  186.     char m_url[255];
  187.     SwsContext *m_img_convert_ctx;//图像转换设置
  188.     AVFormatContext *m_pFormatctx; //视频流
  189.     QAudioThread *m_audiocodec; //音频解码器
  190.     QVideoThread *m_videocodec; //视频解码器
  191.     QSubtitleThread *m_subtitlecodec; //字幕解码器
  192.     QMasterClock masterclock;
  193.     QImage *m_frame;
  194.     uint8_t* framebuffer;//图象存储区 m_rgbframe m_frame 共享
  195.     QMutex m_mutex;
  196.     QFfplay *ffplay;
  197.     bool m_isopen;
  198. };
  199. #endif // QFFMPEG_H

复制代码

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

も星光 2022-09-12 18:49:00

我晕,只有头文件

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文