不用 SDL 的QT+FFMPEG 播放器

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版編譯運行,內存無重大泄露。

作者郵箱 [email protected]

代碼片段(1)

[代碼] cpp代碼

001 #ifndef QFFMPEG_H
002 #define QFFMPEG_H
003  
004 #include <QThreadPool>
005 #include <QRunnable>
006 #include <QWidget>
007 #include <QAudioDeviceInfo>
008 #include <QAudioOutput>
009 #include <QAudioFormat>
010 #include <QThread>
011 #include <QImage>
012 #include <QMutex>
013 #include <QTime>
014 #include <QPainter>
015 #include <QIODevice>
016 #include <QWaitCondition>
017 #include <QSemaphore>
018 #include <QReadWriteLock>
019 #include <QDebug>
020  
021  
022 #include <stdlib.h>
023 #include <stdio.h>
024 #include <memory.h>//注意要包含此頭文件與qDebug函數相關
025 #include <stdint.h>
026 #include <QList>
027  
028  
029 extern "C"
030 {
031 //ffmpeg相關的頭文件
032 #include <libavcodec/avcodec.h>
033 #include <libavutil/common.h>
034 #include <libavutil/avstring.h>
035 #include <libavcodec/avcodec.h>
036 #include <libavformat/avformat.h>
037 #include <libswscale/swscale.h>
038 #include <libavcodec/opt.h>
039 #include <libavformat/avio.h>
040  
041  
042  
043 //#include <libavdevice/avdevice.h>
044  
045 }
046 //播放信息
047  
048 #define DEFAULT_IMAGEFMT QImage::Format_RGB32
049 #define DEFAULT_FRAMEFMT PIX_FMT_RGB32
050 #define MAX_AUDIO_DIFFTIME 1000000  //音頻時間差,最大值
051 #define AUDIOBUFFERSIZE (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2 //音頻緩衝大小
052 #define MAX_BUFFER 50
053  
054  
055 class QMasterClock //主時鐘
056 {
057 public:
058     QMasterClock();
059     void adjusttime(int us);
060     qint64 getuscurtime();
061     void setstarttime(QTime t);
062 protected:
063     QReadWriteLock m;
064     QTime starttime;
065  
066 };
067  
068 class QDecodecThread : public QThread
069 {
070     Q_OBJECT
071 public:
072     QDecodecThread(AVFormatContext *f,AVCodecContext *c,QMasterClock *cl,int index,QObject *parent=0);
073     ~QDecodecThread();
074     void run()=0;
075  
076     void setstreamindex(const int index);
077     int getstreamindex() ;
078     int getusdtime() ;
079     void setusdtime(int dt);
080     void setisend(const bool b);
081     void lockdata();
082     void unlockdata();
083     int getcount() ;
084     void putpacket(AVPacket *p);
085     void free_packet(AVPacket *p);
086     AVPacket* getpacket();
087     qint64 getus(qint64 t);
088     QSemaphore sempfree;
089  
090 protected:
091     AVCodecContext *actx; //解碼器
092     AVFormatContext  *formatctx;
093     int stream_index;
094  
095     QMasterClock *masterclock;
096     QSemaphore semp;
097  
098     bool isend;
099  
100     QList <AVPacket*> pkts;
101  
102     int usdtime;//時間差值,用於修正主時鐘
103     QMutex mutex;
104     qint64 basetime;
105 };
106  
107  
108 class QAudioThread : public QDecodecThread
109 {
110     Q_OBJECT
111 public:
112     QAudioThread(AVFormatContext *f,AVCodecContext *c,QMasterClock *cl,int index,QObject *parent=0);
113     ~QAudioThread();
114     QAudioOutput* getaudio();
115     void run();
116     void play();
117     int ffsampleratetoint(const SampleFormat sf);
118     qint64 caltime(const uint64_t pts);
119 public slots:
120   void notified();
121   void audiostate(QAudio::State state);
122 protected:
123    int writeaudio(char *data ,const int size);
124  
125     QAudioOutput *audio;
126     QIODevice *audioIO;
127  
128  
129 };
130  
131 class QVideoThread : public QDecodecThread
132 {
133    Q_OBJECT
134 public:
135    QVideoThread(AVFormatContext *f, AVCodecContext *c,QMasterClock *cl,int index,QObject *parent=0);
136    ~QVideoThread();
137    qint64 getframebuffer(char *data);
138    int getwidth() const;
139    int getheight() const;
140    int getframesize();
141    void run();
142  
143 protected:
144    SwsContext *m_img_convert_ctx;//圖像轉換設置
145  
146    char *framebuffer;
147    int framebuffersize;
148    qint64 pts;
149  
150    QWaitCondition videowait;
151  
152  
153 private:
154    AVFrame *yuvframe;
155    AVFrame *rgbframe;
156 };
157  
158 class QSubtitleThread : public QDecodecThread
159 {
160     Q_OBJECT
161 public:
162     QSubtitleThread(AVFormatContext *f,AVCodecContext *c,QMasterClock *cl,int index,QObject *parent=0)
163         :QDecodecThread(f,c,cl,index,parent)
164     {}
165     void run(){}
166 };
167  
168 class QFfWidget : public QWidget
169 {
170     Q_OBJECT
171  
172 public:
173     explicit QFfWidget(QWidget *parent = 0);
174     ~QFfWidget();
175     void setframe(QImage *f);
176     void lockframe();
177     void unlockframe();
178 private:
179     QImage *frame;
180     QMutex m;
181 protected:
182     void paintEvent(QPaintEvent *);
183  
184 };
185  
186 class QFfplay : public QThread
187 {
188     Q_OBJECT
189 public:
190     QFfplay(QVideoThread *v,QMasterClock *c, QObject *parent);
191     ~QFfplay();
192     QWidget* getwidget();
193 protected:
194     void run();
195     QVideoThread *video;
196     QMasterClock *masterclock;
197     QImage *frame;
198     char *framebuffer;
199     QFfWidget *widget;
200  
201  
202 };
203  
204 class QFfmpeg : public QThread
205 {
206     Q_OBJECT
207 public:
208     explicit QFfmpeg(QObject *parent);
209     //設置參數
210     void seturl(QString url);
211  
212     bool open();
213     void close();
214  
215     bool play();
216     void stop();
217  
218     //判斷視頻是否結束
219     bool atEnd();
220     bool IsOpen();
221  
222     QWidget* getwidget();
223  
224  
225 signals:
226  
227 public slots:
228  
229 protected:
230  
231     void run();
232 private:
233     /****解碼相關******************/
234     char m_url[255];
235     SwsContext *m_img_convert_ctx;//圖像轉換設置
236  
237     AVFormatContext *m_pFormatctx; //視頻流
238     QAudioThread *m_audiocodec; //音頻解碼器
239     QVideoThread *m_videocodec; //視頻解碼器
240     QSubtitleThread *m_subtitlecodec; //字幕解碼器
241  
242     QMasterClock masterclock;
243  
244     QImage *m_frame;
245     uint8_t* framebuffer;//圖象存儲區 m_rgbframe m_frame 共享
246  
247     QMutex m_mutex;
248     QFfplay *ffplay;
249     bool m_isopen;
250  
251 };
252  
253 #endif // QFFMPEG_H

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章