Skip to content

Commit

Permalink
new AVDecoder api
Browse files Browse the repository at this point in the history
  • Loading branch information
wang-bin committed Oct 17, 2013
1 parent 32b94c4 commit 75f7d70
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 19 deletions.
95 changes: 90 additions & 5 deletions src/AVDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,78 @@ AVDecoder::~AVDecoder()
{
}

bool AVDecoder::open()
{
DPTR_D(AVDecoder);
if (!d.codec_ctx) {
qWarning("FFmpeg codec context not ready");
return false;
}
AVCodec *codec = 0;
if (!d.name.isEmpty()) {
codec = avcodec_find_decoder_by_name(d.name.toUtf8().constData());
} else {
codec = avcodec_find_decoder(d.codec_ctx->codec_id);
}
if (!codec) {
if (d.name.isEmpty()) {
qWarning("No codec could be found with id %d", d.codec_ctx->codec_id);
} else {
qWarning("No codec could be found with name %s", d.name.toUtf8().constData());
}
return false;
}

//setup codec context
if (d.low_resolution > codec->max_lowres) {
qWarning("Use the max value for lowres supported by the decoder (%d)", codec->max_lowres);
d.low_resolution = codec->max_lowres;
}
d.codec_ctx->lowres = d.low_resolution;
if (d.codec_ctx->lowres) {
d.codec_ctx->flags |= CODEC_FLAG_EMU_EDGE;
}
if (d.fast) {
d.codec_ctx->flags2 |= CODEC_FLAG2_FAST;
} else {
//d.codec_ctx->flags2 &= ~CODEC_FLAG2_FAST; //ffplay has no this
}
if (codec->capabilities & CODEC_CAP_DR1) {
d.codec_ctx->flags |= CODEC_FLAG_EMU_EDGE;
}
//set thread
if (d.threads == -1)
d.threads = qMax(0, QThread::idealThreadCount());
if (d.threads > 0)
d.codec_ctx->thread_count = d.threads;
if (d.threads > 1)
d.codec_ctx->thread_type = d.thread_slice ? FF_THREAD_SLICE : FF_THREAD_FRAME;

//set dict used by avcodec_open2(). see ffplay
// AVDictionary *opts;
int ret = avcodec_open2(d.codec_ctx, codec, NULL);
if (ret < 0) {
qWarning("open video codec failed: %s", av_err2str(ret));
return false;
}
return true;
}

bool AVDecoder::close()
{
DPTR_D(AVDecoder);
if (!d.codec_ctx) {
qWarning("FFmpeg codec context not ready");
return false;
}
int ret = avcodec_close(d.codec_ctx);
if (ret < 0) {
qWarning("failed to close decoder: %s", av_err2str(ret));
return false;
}
return true;
}

void AVDecoder::flush()
{
if (isAvailable())
Expand All @@ -49,6 +121,7 @@ void AVDecoder::setCodecContext(AVCodecContext *codecCtx)
d.codec_ctx = codecCtx;
}

//TODO: reset other parameters?
AVCodecContext* AVDecoder::codecContext() const
{
return d_func().codec_ctx;
Expand All @@ -59,6 +132,17 @@ void AVDecoder::setLowResolution(int lowres)
d_func().low_resolution = lowres;
}

void AVDecoder::setCodecName(const QString &name)
{
d_func().name = name;
}

QString AVDecoder::codecName() const
{
DPTR_D(const AVDecoder);
return d.name.isEmpty() ? d.codec_ctx->codec->name : d.name;
}

int AVDecoder::lowResolution() const
{
return d_func().low_resolution;
Expand All @@ -67,8 +151,8 @@ int AVDecoder::lowResolution() const
void AVDecoder::setDecodeThreads(int threads)
{
DPTR_D(AVDecoder);
d.threads = threads > 0 ? threads : QThread::idealThreadCount();
d.threads = qMax(d.threads, 1);
d.threads = threads;// threads >= 0 ? threads : qMax(0, QThread::idealThreadCount());
d.threads = qMax(d.threads, 0); //check max?
}

int AVDecoder::decodeThreads() const
Expand All @@ -95,11 +179,12 @@ bool AVDecoder::prepare()
}
qDebug("Decoding threads count: %d", d.threads);
#if DECODER_DONE //currently codec context is opened in demuxer, we must setup context before open
d.codec_ctx->thread_count = d.threads;
if (d.threads > 0)
d.codec_ctx->thread_count = d.threads;
if (d.threads > 1)
d.codec_ctx->thread_type = d.thread_slice ? FF_THREAD_SLICE : FF_THREAD_FRAME;
else
d.codec_ctx->thread_type = 0; //FF_THREAD_FRAME:1, FF_THREAD_SLICE:2
//else
// d.codec_ctx->thread_type = 0; //FF_THREAD_FRAME:1, FF_THREAD_SLICE:2

//? !CODEC_ID_H264 && !CODEC_ID_VP8
d.codec_ctx->lowres = d.low_resolution;
Expand Down
23 changes: 13 additions & 10 deletions src/AVDemuxer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ void AVDemuxer::seek(qreal q)
//AVSEEK_FLAG_BACKWARD has no effect? because we know the timestamp
// FIXME: back flag is opposite? otherwise seek is bad and may crash?
int seek_flag = (backward ? 0 : AVSEEK_FLAG_BACKWARD); //AVSEEK_FLAG_ANY
//bool seek_bytes = !!(format_context->iformat->flags & AVFMT_TS_DISCONT) && strcmp("ogg", format_context->iformat->name);
int ret = av_seek_frame(format_context, -1, t, seek_flag);
//avformat_seek_file()
#endif
Expand Down Expand Up @@ -450,6 +451,8 @@ bool AVDemuxer::openCodecs()
if (a_codec_context) {
AVCodec *aCodec = avcodec_find_decoder(a_codec_context->codec_id);
if (aCodec) {
if (aCodec->capabilities & CODEC_CAP_DR1)
a_codec_context->flags |= CODEC_FLAG_EMU_EDGE;
ret = avcodec_open2(a_codec_context, aCodec, NULL);
if (ret < 0) {
_has_audio = false;
Expand Down Expand Up @@ -478,15 +481,7 @@ bool AVDemuxer::openCodecs()
_has_vedio = false;
}
////v_codec_context->time_base = (AVRational){1,30};
//avcodec_open(v_codec_context, vCodec) //deprecated
ret = avcodec_open2(v_codec_context, vCodec, NULL);
if (ret < 0) {
qWarning("open video codec failed: %s", av_err2str(ret));
_has_vedio = false;
} else {
if (vCodec->capabilities & CODEC_CAP_DR1)
v_codec_context->flags |= CODEC_FLAG_EMU_EDGE;
}
///
// TODO: move to AVDecoder
//if (hurry_up) {
// codec_ctx->skip_frame = AVDISCARD_NONREF;
Expand All @@ -499,6 +494,14 @@ bool AVDemuxer::openCodecs()
//}
bool skipframes = false;
v_codec_context->skip_frame = skipframes ? AVDISCARD_NONREF : AVDISCARD_DEFAULT;
if (vCodec->capabilities & CODEC_CAP_DR1)
v_codec_context->flags |= CODEC_FLAG_EMU_EDGE;
//avcodec_open(v_codec_context, vCodec) //deprecated
ret = avcodec_open2(v_codec_context, vCodec, NULL);
if (ret < 0) {
qWarning("open video codec failed: %s", av_err2str(ret));
_has_vedio = false;
}
}
started_ = false;
return _has_audio || _has_vedio;
Expand Down Expand Up @@ -534,7 +537,7 @@ bool AVDemuxer::autoResetStream() const
{
return auto_reset_stream;
}

//TODO: code like setStream, simplify
bool AVDemuxer::setStreamIndex(StreamType st, int index)
{
QList<int> *streams = 0;
Expand Down
12 changes: 11 additions & 1 deletion src/QtAV/AVDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,23 @@ class Q_EXPORT AVDecoder
public:
AVDecoder();
virtual ~AVDecoder();
/*
* default is open FFmpeg codec context
* codec config must be done before open
*/
virtual bool open();
virtual bool close();
void flush();
void setCodecContext(AVCodecContext* codecCtx); //protected
AVCodecContext* codecContext() const;
// force a codec
void setCodecName(const QString& name);
QString codecName() const;

//? low resolution decoding, 0: normal, 1-> 1/2 size, 2->1/4 size
void setLowResolution(int lowres);
int lowResolution() const;
// 0: auto detect by av_cpu_count()
// -1: auto detect by QThread::idealThreadCount(). 0: set by ffmpeg(default)
void setDecodeThreads(int threads);
int decodeThreads() const;
void setThreadSlice(bool s);
Expand Down
6 changes: 4 additions & 2 deletions src/QtAV/AVDemuxer.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ class Q_EXPORT AVDemuxer : public QObject //QIODevice?
bool close();
bool loadFile(const QString& fileName);
bool isLoaded(const QString& fileName) const;
bool openCodecs();
bool closeCodecs();
Q_DECL_DEPRECATED bool openCodecs();
Q_DECL_DEPRECATED bool closeCodecs();

void putFlushPacket();
bool readFrame();
Expand All @@ -83,6 +83,8 @@ class Q_EXPORT AVDemuxer : public QObject //QIODevice?

void setClock(AVClock *c);
AVClock *clock() const;

bool isSeekable() const;
void setSeekUnit(SeekUnit unit);
SeekUnit seekUnit() const;
void setSeekTarget(SeekTarget target);
Expand Down
5 changes: 4 additions & 1 deletion src/QtAV/private/AVDecoder_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,14 @@ class Q_EXPORT AVDecoderPrivate : public DPtrPrivate<AVDecoder>
AVDecoderPrivate():
codec_ctx(0)
, available(true)
, fast(false)
, frame(0)
, got_frame_ptr(0)
, thread_slice(1)
, low_resolution(0)
{
frame = avcodec_alloc_frame();
threads = qMax(1, QThread::idealThreadCount()); //av_cpu_count is not available for old ffmpeg. c++11 thread::hardware_concurrency()
threads = qMax(0, QThread::idealThreadCount()); //av_cpu_count is not available for old ffmpeg. c++11 thread::hardware_concurrency()
}
virtual ~AVDecoderPrivate() {
if (frame) {
Expand All @@ -52,13 +53,15 @@ class Q_EXPORT AVDecoderPrivate : public DPtrPrivate<AVDecoder>

AVCodecContext *codec_ctx; //set once and not change
bool available;
bool fast;
AVFrame *frame; //set once and not change
QByteArray decoded;
int got_frame_ptr;
QMutex mutex;
int threads;
bool thread_slice;
int low_resolution;
QString name;
};

} //namespace QtAV
Expand Down

0 comments on commit 75f7d70

Please sign in to comment.