不用 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]
标签: ffmpeg 播放器 SDL QT

代码片段(1)

[代码] cpp代码

view source print ?
001 #ifndef QFFMPEG_H
002 #define QFFMPEG_H
003  
004 #include
005 #include
006 #include
007 #include
008 #include
009 #include
010 #include
011 #include
012 #include
013 #include
014 #include
015 #include
016 #include
017 #include
018 #include
019 #include
020  
021  
022 #include
023 #include
024 #include //注意要包含此头文件与qDebug函数相关
025 #include
026 #include
027  
028  
029 extern "C"
030 {
031 //ffmpeg相关的头文件
032 #include
033 #include
034 #include
035 #include
036 #include
037 #include
038 #include
039 #include
040  
041  
042  
043 //#include
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 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

你可能感兴趣的:(不用 SDL 的QT+FFMPEG 播放器)