-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
2015-04-26 17:18:23
- Loading branch information
Showing
139 changed files
with
31,405 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#------------------------------------------------- | ||
# | ||
# | ||
# | ||
#------------------------------------------------- | ||
|
||
QT += core gui widgets network | ||
|
||
CONFIG += app | ||
|
||
|
||
|
||
SOURCES += main.cpp\ | ||
mainwindow.cpp \ | ||
QFFmpegPlayer.cpp \ | ||
QFFmpegAudioDecoder.cpp \ | ||
QFFmpegVideoDecoder.cpp \ | ||
QOpenALEngine.cpp \ | ||
QFFmpegGLWidget.cpp \ | ||
QFFmpegClock.cpp \ | ||
QFFmpegVideoRender.cpp | ||
|
||
HEADERS += mainwindow.h \ | ||
QFFmpegPlayer.h \ | ||
QFFmpegAudioDecoder.h \ | ||
QFFmpegVideoDecoder.h \ | ||
QOpenALEngine.h \ | ||
QFFmpegGLWidget.h \ | ||
QFFmpegClock.h \ | ||
QFFmpegVideoRender.h | ||
|
||
FORMS += mainwindow.ui | ||
|
||
LIBS += -L$$PWD/ffmpeg/lib -lavcodec -lavdevice -lavfilter -lavformat -lavutil -lpostproc -lswscale -lswresample | ||
INCLUDEPATH += $$PWD/ffmpeg/include | ||
|
||
LIBS += -L$$PWD/openal/libs/Win32 -lOpenAL32 | ||
INCLUDEPATH += $$PWD/openal/include/AL | ||
|
||
|
||
RESOURCES += | ||
|
||
DISTFILES += |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,238 @@ | ||
#include "QFFmpegAudioDecoder.h" | ||
#include <QDebug> | ||
|
||
|
||
static uint8_t audio_buf[10240]; | ||
uint8_t *buff[]={audio_buf}; | ||
|
||
|
||
|
||
void QFFmpegAudioDecoder::setStream(AVStream *mStream) | ||
{ | ||
this->mStream=mStream; | ||
qDebug("+++++++++++++++"); | ||
} | ||
|
||
void QFFmpegAudioDecoder::setClock(QFFmpegClock *clock) | ||
{ | ||
this->mClock=clock; | ||
} | ||
double QFFmpegAudioDecoder::getAudioTime() | ||
{ | ||
if(mBufferTimes.length()>0) | ||
{ | ||
float tt=al->getBufferTimeOffset(); | ||
//qDebug("--- %f %f",mBufferTimes.at(0),tt); | ||
return mBufferTimes.at(0)+tt; | ||
} | ||
else | ||
return 0; | ||
|
||
} | ||
|
||
void QFFmpegAudioDecoder::timerStart() | ||
{ | ||
timer->start(); | ||
} | ||
void QFFmpegAudioDecoder::timerUpdate() | ||
{ | ||
if(mBufferTimes.length()>0) | ||
{ | ||
float tt=al->getBufferTimeOffset(); | ||
//qDebug("play:%lf",mBufferTimes.at(0)+tt); | ||
} | ||
|
||
} | ||
|
||
QFFmpegAudioDecoder::QFFmpegAudioDecoder(QObject *parent) : QThread(parent) | ||
{ | ||
mAudioClock=0; | ||
mBufferStartTime=0; | ||
|
||
queue.clear(); | ||
QOpenALEngine::init(); | ||
|
||
al=new QOpenALEngine(); | ||
timer=new QTimer(); | ||
timer->setInterval(20); | ||
connect(timer,SIGNAL(timeout()),this,SLOT(timerUpdate())); | ||
|
||
} | ||
|
||
QFFmpegAudioDecoder::~QFFmpegAudioDecoder() | ||
{ | ||
qDebug("================="); | ||
QOpenALEngine::deinit(); | ||
} | ||
|
||
|
||
|
||
void QFFmpegAudioDecoder::setCodecCtx(AVCodecContext *mAudioCtx) | ||
{ | ||
this->mAudioCtx=mAudioCtx; | ||
|
||
swr_ctx = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, | ||
mAudioCtx->sample_rate, mAudioCtx->channel_layout, | ||
mAudioCtx->sample_fmt, mAudioCtx->sample_rate, 0, NULL); | ||
if (swr_init(swr_ctx) < 0) { | ||
qDebug("Failed to initialize the resampling context\n"); | ||
} | ||
} | ||
|
||
|
||
void QFFmpegAudioDecoder::run() | ||
{ | ||
AVFrame *frame = av_frame_alloc(); | ||
|
||
int got_frame = 0; | ||
int ret=0; | ||
AVPacket pkt_temp,pkt; | ||
int packet_pending=0; | ||
int64_t next_pts; | ||
AVRational next_pts_tb; | ||
|
||
pkt_temp.data=0; | ||
pkt.data=0; | ||
|
||
while(true) | ||
{ | ||
|
||
if(!packet_pending) | ||
{ | ||
if(pkt.data)av_free_packet(&pkt); | ||
// qDebug("----:%d",pkt_temp.data); | ||
bool rr=sema.tryAcquire(1,20); | ||
if(!rr) continue; | ||
mutex.lock(); | ||
pkt_temp =pkt=queue.dequeue().pkt; | ||
mutex.unlock(); | ||
|
||
|
||
packet_pending = 1; | ||
} | ||
|
||
|
||
//解码一帧 | ||
do { | ||
int ret = -1; | ||
|
||
|
||
ret = avcodec_decode_audio4(mAudioCtx, frame, &got_frame, &pkt_temp); | ||
//qDebug("%d %d %d",ret,got_frame,pkt_temp.pts); | ||
|
||
if (got_frame) { | ||
AVRational tb; | ||
tb.num=1; | ||
tb.den=frame->sample_rate; | ||
|
||
if (frame->pts != AV_NOPTS_VALUE) | ||
frame->pts = av_rescale_q(frame->pts, mAudioCtx->time_base, tb); | ||
else if (frame->pkt_pts != AV_NOPTS_VALUE) | ||
frame->pts = av_rescale_q(frame->pkt_pts, av_codec_get_pkt_timebase(mAudioCtx), tb); | ||
else if (next_pts != AV_NOPTS_VALUE) | ||
frame->pts = av_rescale_q(next_pts, next_pts_tb, tb); | ||
if (frame->pts != AV_NOPTS_VALUE) { | ||
next_pts = frame->pts + frame->nb_samples; | ||
next_pts_tb = tb; | ||
} | ||
} | ||
|
||
|
||
|
||
|
||
if (ret < 0) { | ||
packet_pending = 0; | ||
} else { | ||
//qDebug("get===%d",pkt_temp.size); | ||
pkt_temp.dts = pkt_temp.pts = AV_NOPTS_VALUE; | ||
if (pkt_temp.data) { | ||
pkt_temp.data += ret; | ||
pkt_temp.size -= ret; | ||
if (pkt_temp.size <= 0) | ||
packet_pending = 0; | ||
} else { | ||
if (!got_frame) { | ||
packet_pending = 0; | ||
// finished = pkt_serial; | ||
} | ||
} | ||
} | ||
|
||
if(!packet_pending) break; | ||
|
||
|
||
}while (!got_frame); | ||
|
||
|
||
//qDebug("12345:%d",packet_pending); | ||
|
||
|
||
|
||
while(true) | ||
{ | ||
int pnum=al->getProcessedNum(); | ||
int qnum=al->getQueuedNum(); | ||
QOpenALEngine::State state=al->getState(); | ||
|
||
if((state!=QOpenALEngine::PLAYING) || (state==QOpenALEngine::PLAYING && pnum>1)) | ||
{ | ||
double dpts = NAN; | ||
if (frame->pts != AV_NOPTS_VALUE) | ||
dpts = av_q2d(mStream->time_base) * frame->pts; | ||
|
||
//qDebug("play:%lf",dpts); | ||
|
||
int len=swr_convert(swr_ctx,buff,10240, | ||
(const uint8_t **) frame->data,frame->nb_samples); | ||
|
||
len=len*2*av_get_bytes_per_sample(AV_SAMPLE_FMT_S16); | ||
al->write(buff[0],len,mAudioCtx->sample_rate); | ||
|
||
if(mBufferTimes.length()>=4) | ||
mBufferTimes.dequeue(); | ||
mBufferTimes.enqueue(dpts); | ||
|
||
if(qnum==4 && state!=QOpenALEngine::PLAYING) | ||
{ | ||
mBufferStartTime=dpts; | ||
al->play(); | ||
mClock->start(); | ||
QTimer::singleShot(0,this,SLOT(timerStart())); | ||
} | ||
|
||
|
||
break; | ||
} | ||
else QThread::msleep(20); | ||
} | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
} | ||
|
||
} | ||
|
||
|
||
void QFFmpegAudioDecoder::addPacket(AVPacket pkt) | ||
{ | ||
|
||
FFAVPacket avpkt; | ||
avpkt.pkt=pkt; | ||
mutex.lock(); | ||
queue.enqueue(avpkt); | ||
sema.release(); | ||
mutex.unlock(); | ||
|
||
} | ||
|
||
|
||
int QFFmpegAudioDecoder::getQueueLength() | ||
{ | ||
return queue.length(); | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
#ifndef QFFMPEGAUDIODECODER_H | ||
#define QFFMPEGAUDIODECODER_H | ||
|
||
#include <QThread> | ||
#include <QQueue> | ||
#include <QMutex> | ||
#include <QSemaphore> | ||
#include "QOpenALEngine.h" | ||
#include <QTimer> | ||
#include <QQueue> | ||
#include "QFFmpegClock.h" | ||
|
||
extern "C"{ | ||
#include "libavutil/avstring.h" | ||
#include "libavutil/mathematics.h" | ||
#include "libavutil/pixdesc.h" | ||
#include "libavutil/imgutils.h" | ||
#include "libavutil/dict.h" | ||
#include "libavutil/parseutils.h" | ||
#include "libavutil/samplefmt.h" | ||
#include "libavutil/avassert.h" | ||
#include "libavutil/time.h" | ||
#include "libavformat/avformat.h" | ||
#include "libavdevice/avdevice.h" | ||
#include "libswscale/swscale.h" | ||
#include "libavutil/opt.h" | ||
#include "libavcodec/avfft.h" | ||
#include "libswresample/swresample.h" | ||
} | ||
|
||
typedef struct FFAVPacket { | ||
AVPacket pkt; | ||
int serial; | ||
} FFAVPacket; | ||
|
||
|
||
class QFFmpegAudioDecoder : public QThread | ||
{ | ||
Q_OBJECT | ||
public: | ||
explicit QFFmpegAudioDecoder(QObject *parent = 0); | ||
~QFFmpegAudioDecoder(); | ||
|
||
|
||
void setCodecCtx(AVCodecContext *mAudioCtx); | ||
void setStream(AVStream *mStream); | ||
void addPacket(AVPacket pkt); | ||
int getQueueLength(); | ||
|
||
void setClock(QFFmpegClock *clock); | ||
double getAudioTime(); | ||
signals: | ||
|
||
public slots: | ||
private: | ||
AVCodecContext *mAudioCtx; | ||
QQueue<FFAVPacket> queue; | ||
QMutex mutex; | ||
QSemaphore sema; | ||
SwrContext *swr_ctx; | ||
QOpenALEngine *al; | ||
QTimer *timer; | ||
AVStream *mStream; | ||
|
||
double mAudioClock; | ||
double mBufferStartTime; | ||
QQueue<double> mBufferTimes; | ||
|
||
QFFmpegClock *mClock; | ||
protected: | ||
void run(); | ||
private slots: | ||
void timerUpdate(); | ||
void timerStart(); | ||
}; | ||
|
||
#endif // QFFMPEGAUDIODECODER_H |
Oops, something went wrong.