不用 SDL 的QT+FFMPEG 播放器
2011-12-09 10:44
253 查看
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版编译运行,内存无重大泄露。
作者邮箱 lbwave@sina.com
标签:
ffmpeg
播放器
SDL
QT
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版编译运行,内存无重大泄露。
作者邮箱 lbwave@sina.com
标签:
ffmpeg
播放器
SDL
QT
代码片段(1)
[代码] cpp代码
view sourceprint?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 |
相关文章推荐
- 最简单的基于FFMPEG+SDL的音频播放器
- ffmpeg+sdl教程——编写一个简单的播放器3(为视频加入音频)
- 第一章:ffmpeg和QT开发播放器之环境搭建
- 第二章:ffmpeg和QT开发播放器之初尝试
- Qt + ffmpeg+SDl
- QT+FFMPEG播放器——github代码
- Qt + FFmpeg 本地音频播放器
- qt+FFMPEG(不需要SDL)
- 最简单的基于FFMPEG+SDL的音频播放器 ver2 (采用SDL2.0)
- 最简单的基于FFMPEG+SDL的音频播放器
- ffmpeg+sdl教程——编写一个简单的播放器4(让程序更模块化)
- Ffmpeg+QT简单播放器的设计
- 第三章:ffmpeg和QT开发播放器之视频的解码转码
- ffmpeg系列:基于QT的播放器界面绘制
- (转译)用FFmpeg和SDL写播放器--03播放声音
- 播放器(一)-FFMPEG-SDL-MFC-本地文件
- 最简单的基于FFMPEG+SDL的视频播放器:拆分-解码器和播放器
- 最简单的基于FFMPEG+SDL的音频播放器
- ffmpeg+sdl教程----编写一个简单的播放器2(输出视频到屏幕)
- Qt中使用SDL和FFmpeg的编译问题