QT FFMPEG 播放器
不用SDL 的QT+FFMPEG 播放器,內(nèi)容如下:
1、不用SDL的理由
SDL是為游戲開發(fā)的,大量的依賴硬件加速。不用sdl是為了能方便的將程序移植到其他的平臺 。本人受條件限制未向其他系統(tǒng)移植。但由于沒采用QT(ffmpeg)之外的其他第三方代碼,相信移植是個很小的問題。本人曾經(jīng)做過arm920+qt+linux(fambuffer)的開發(fā)。
本程序僅用了Qwideg來顯示,就是為了移植方便。ffmpeg用C寫的可以向多種平臺移植。
2、如何實現(xiàn)音頻視頻同步
本范例采用系統(tǒng)時鐘作為主時鐘,用音頻時鐘校正主時鐘。
3、如何實現(xiàn)多趨緩沖
本范例采用多線程處理機制。
(1)QFfmpeg :主要負責讀取數(shù)據(jù)包,存入QList列表.壓縮前的數(shù)據(jù)占用空間小。緩沖大小可設(shè),按視頻幀數(shù)和聲卡緩沖大小決定
(2)QAudioThread:音頻解碼
(3)QVideoThread:視頻解碼
(4)QFfPlay :播放 (沒有用定時器,定時器誤差太大)
4、本范例實現(xiàn)QT+ffmpeg播放器的基本功能。
僅出于愛好開發(fā),未進行系統(tǒng)排錯,用于大家參考交流。 在開發(fā)期間參考了ffplay 。
5、實現(xiàn)在QT4.6 QT4.7forwindows版編譯運行,內(nèi)存無重大泄露
cpp代碼
- #ifndef QFFMPEG_H
- #define QFFMPEG_H
- #include <QThreadPool>
- #include <QRunnable>
- #include <QWidget>
- #include <QAudioDeviceInfo>
- #include <QAudioOutput>
- #include <QAudioFormat>
- #include <QThread>
- #include <QImage>
- #include <QMutex>
- #include <QTime>
- #include <QPainter>
- #include <QIODevice>
- #include <QWaitCondition>
- #include <QSemaphore>
- #include <QReadWriteLock>
- #include <QDebug>
- #include <stdlib.h>
- #include <stdio.h>
- #include <memory.h>//注意要包含此頭文件與qDebug函數(shù)相關(guān)
- #include <stdint.h>
- #include <QList>
- extern "C"
- {
- //ffmpeg相關(guān)的頭文件
- #include <libavcodec/avcodec.h>
- #include <libavutil/common.h>
- #include <libavutil/avstring.h>
- #include <libavcodec/avcodec.h>
- #include <libavformat/avformat.h>
- #include <libswscale/swscale.h>
- #include <libavcodec/opt.h>
- #include <libavformat/avio.h>
- //#include <libavdevice/avdevice.h>
- }
- //播放信息
- #define DEFAULT_IMAGEFMT QImage::Format_RGB32
- #define DEFAULT_FRAMEFMT PIX_FMT_RGB32
- #define MAX_AUDIO_DIFFTIME 1000000 //音頻時間差,最大值
- 1 #define AUDIOBUFFERSIZE (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2 //音頻緩沖大小
- #define MAX_BUFFER 50
- class QMasterClock //主時鐘
- {
- public:
- QMasterClock();
- void adjusttime(int us);
- qint64 getuscurtime();
- void setstarttime(QTime t);
- protected:
- QReadWriteLock m;
- QTime starttime;
- };
- class QDecodecThread : public QThread
- {
- Q_OBJECT
- public:
- QDecodecThread(AVFormatContext *f,AVCodecContext *c,QMasterClock *cl,int index,QObject *parent=0);
- ~QDecodecThread();
- void run()=0;
- void setstreamindex(const int index);
- int getstreamindex() ;
- int getusdtime() ;
- void setusdtime(int dt);
- void setisend(const bool b);
- void lockdata();
- void unlockdata();
- int getcount() ;
- void putpacket(AVPacket *p);
- void free_packet(AVPacket *p);
- AVPacket* getpacket();
- qint64 getus(qint64 t);
- QSemaphore sempfree;
- protected:
- AVCodecContext *actx; //解碼器
- AVFormatContext *formatctx;
- int stream_index;
- QMasterClock *masterclock;
- QSemaphore semp;
- bool isend;
- QList <AVPacket*> pkts;
- int usdtime;//時間差值,用于修正主時鐘
- QMutex mutex;
- qint64 basetime;
- };
- class QAudioThread : public QDecodecThread
- {
- Q_OBJECT
- public:
- QAudioThread(AVFormatContext *f,AVCodecContext *c,QMasterClock *cl,int index,QObject *parent=0);
- ~QAudioThread();
- QAudioOutput* getaudio();
- void run();
- void play();
- int ffsampleratetoint(const SampleFormat sf);
- qint64 caltime(const uint64_t pts);
- public slots:
- void notified();
- void audiostate(QAudio::State state);
- protected:
- int writeaudio(char *data ,const int size);
- QAudioOutput *audio;
- QIODevice *audioIO;
- };
- class QVideoThread : public QDecodecThread
- {
- Q_OBJECT
- public:
- QVideoThread(AVFormatContext *f, AVCodecContext *c,QMasterClock *cl,int index,QObject *parent=0);
- ~QVideoThread();
- qint64 getframebuffer(char *data);
- int getwidth() const;
- int getheight() const;
- int getframesize();
- void run();
- protected:
- SwsContext *m_img_convert_ctx;//圖像轉(zhuǎn)換設(shè)置
- char *framebuffer;
- int framebuffersize;
- qint64 pts;
- QWaitCondition videowait;
- private:
- AVFrame *yuvframe;
- AVFrame *rgbframe;
- };
- class QSubtitleThread : public QDecodecThread
- {
- ,Q_OBJECT
- public:
- QSubtitleThread(AVFormatContext *f,AVCodecContext *c,QMasterClock *cl,int index,QObject *parent=0)
- :QDecodecThread(f,c,cl,index,parent)
- {}
- void run(){}
- };
- class QFfWidget : public QWidget
- {
- Q_OBJECT
- public:
- explicit QFfWidget(QWidget *parent = 0);
- ~QFfWidget();
- void setframe(QImage *f);
- void lockframe();
- void unlockframe();
- private:
- QImage *frame;
- QMutex m;
- protected:
- void paintEvent(QPaintEvent *);
- };
- class QFfplay : public QThread
- {
- Q_OBJECT
- public:
- QFfplay(QVideoThread *v,QMasterClock *c, QObject *parent);
- ~QFfplay();
- QWidget* getwidget();
- protected:
- void run();
- QVideoThread *video;
- QMasterClock *masterclock;
- QImage *frame;
- char *framebuffer;
- QFfWidget *widget;
- };
- class QFfmpeg : public QThread
- {
- Q_OBJECT
- public:
- explicit QFfmpeg(QObject *parent);
- //設(shè)置參數(shù)
- void seturl(QString url);
- bool open();
- void close();
- bool play();
- void stop();
- //判斷視頻是否結(jié)束
- bool atEnd();
- bool IsOpen();
- QWidget* getwidget();
- signals:
- public slots:
- protected:
- void run();
- private:
- /****解碼相關(guān)******************/
- char m_url[255];
- SwsContext *m_img_convert_ctx;//圖像轉(zhuǎn)換設(shè)置
- AVFormatContext *m_pFormatctx; //視頻流
- QAudioThread *m_audiocodec; //音頻解碼器
- QVideoThread *m_videocodec; //視頻解碼器
- QSubtitleThread *m_subtitlecodec; //字幕解碼器
- QMasterClock masterclock;
- QImage *m_frame;
- uint8_t* framebuffer;//圖象存儲區(qū) m_rgbframe m_frame 共享
- QMutex m_mutex;
- QFfplay *ffplay;
- bool m_isopen;
- };
- #endif // QFFMPEG_H
以上是代碼實現(xiàn)。
【編輯推薦】