免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 6980 | 回复: 1

不用 SDL 的QT+FFMPEG 播放器 [复制链接]

论坛徽章:
0
发表于 2011-02-12 11:49 |显示全部楼层
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
复制代码

论坛徽章:
0
发表于 2011-02-25 08:54 |显示全部楼层
我晕,只有头文件
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP