Skip to content

Commit

Permalink
dec: simplify ffmpeg hwa decoder creation
Browse files Browse the repository at this point in the history
VideoDecoder::create("MMAL") equals to VideoDecoder::create()-
>setProperty("hwaccel", "mmal")
  • Loading branch information
wang-bin committed Nov 5, 2016
1 parent 24f8ea2 commit 7ac04eb
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/QtAV/AVPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ class Q_AV_EXPORT AVPlayer : public QObject
/*!
* \brief setVideoDecoderPriority
* also can set in opt.priority
* \param names the video decoder name list in priority order. Name can be "FFmpeg", "CUDA", "DXVA", "D3D11", "VAAPI", "VDA", "VideoToolbox", case insensitive
* \param names the video decoder name list in priority order. Name can be "FFmpeg", "CUDA", "DXVA", "D3D11", "VAAPI", "VDA", "VideoToolbox", "MediaCodec", "MMAL", "QSV", "CrystalHD", case insensitive
*/
void setVideoDecoderPriority(const QStringList& names);
QStringList videoDecoderPriority() const;
Expand Down
4 changes: 4 additions & 0 deletions src/QtAV/VideoDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class Q_AV_EXPORT VideoDecoder : public AVDecoder
private:
template<class C> static VideoDecoder* create() { return new C();}
typedef VideoDecoder* (*VideoDecoderCreator)();
protected:
static bool Register(VideoDecoderId id, VideoDecoderCreator, const char *name);
protected:
VideoDecoder(VideoDecoderPrivate& d);
Expand All @@ -102,5 +103,8 @@ extern Q_AV_EXPORT VideoDecoderId VideoDecoderId_Cedarv;
extern Q_AV_EXPORT VideoDecoderId VideoDecoderId_VDA;
extern Q_AV_EXPORT VideoDecoderId VideoDecoderId_VideoToolbox;
extern Q_AV_EXPORT VideoDecoderId VideoDecoderId_MediaCodec;
extern Q_AV_EXPORT VideoDecoderId VideoDecoderId_MMAL;
extern Q_AV_EXPORT VideoDecoderId VideoDecoderId_QSV;
extern Q_AV_EXPORT VideoDecoderId VideoDecoderId_CrystalHD;
} //namespace QtAV
#endif // QTAV_VIDEODECODER_H
21 changes: 17 additions & 4 deletions src/codec/AVDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

namespace QtAV {

static AVCodec* get_codec(const QString &name, AVCodecID cid)
static AVCodec* get_codec(const QString &name, const QString& hwa, AVCodecID cid)
{
AVCodec *codec = 0;
if (!name.isEmpty()) {
Expand All @@ -37,6 +37,14 @@ static AVCodec* get_codec(const QString &name, AVCodecID cid)
if (cd)
codec = avcodec_find_decoder(cd->id);
}
} else if (!hwa.isEmpty()) {
const QString name_hwa = QString("%1_%2").arg(avcodec_get_name(cid)).arg(hwa);
codec = avcodec_find_decoder_by_name(name_hwa.toUtf8().constData());
if (!codec) {
const AVCodecDescriptor* cd = avcodec_descriptor_get_by_name(name_hwa.toUtf8().constData());
if (cd)
codec = avcodec_find_decoder(cd->id);
}
} else {
codec = avcodec_find_decoder(cid);
}
Expand Down Expand Up @@ -72,11 +80,14 @@ bool AVDecoder::open()
qWarning("FFmpeg codec context not ready");
return false;
}
AVCodec* codec = get_codec(codecName(), d.codec_ctx->codec_id);
if (!codec) { // TODO: can be null for none-ffmpeg based decoders
const QString hwa = property("hwaccel").toString();
AVCodec* codec = get_codec(codecName(), hwa, d.codec_ctx->codec_id);
if (!codec) { // TODO: can be null for none-ffmpeg based decoders
QString es(tr("No codec could be found for '%1'"));
if (d.codec_name.isEmpty()) {
es = es.arg(QLatin1String(avcodec_get_name(d.codec_ctx->codec_id)));
if (!hwa.isEmpty())
es.append('_').append(hwa);
} else {
es = es.arg(d.codec_name);
}
Expand Down Expand Up @@ -107,6 +118,8 @@ bool AVDecoder::open()
d.applyOptionsForDict();
av_opt_set_int(d.codec_ctx, "refcounted_frames", d.enableFrameRef(), 0); // why dict may have no effect?
// TODO: only open for ff decoders
//av_dict_set(&d.dict, "lowres", "1", 0);
// dict is used for a specified AVCodec options (priv_class), av_opt_set_xxx(avctx) is only for avctx
AV_ENSURE_OK(avcodec_open2(d.codec_ctx, codec, d.options.isEmpty() ? NULL : &d.dict), false);
d.is_open = true;
static const char* thread_name[] = { "Single", "Frame", "Slice"};
Expand Down Expand Up @@ -259,7 +272,7 @@ void AVDecoderPrivate::applyOptionsForContext()
// av_opt_set_defaults(codec_ctx); //can't set default values! result maybe unexpected
return;
}
// TODO: use QVariantMap only

if (!options.contains(QStringLiteral("avcodec")))
return;
// workaround for VideoDecoderFFmpeg. now it does not call av_opt_set_xxx, so set here in dict
Expand Down
4 changes: 4 additions & 0 deletions src/codec/video/VideoDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ VideoDecoderId VideoDecoderId_Cedarv = mkid::id32base36_6<'C', 'e', 'd', 'a', 'r
VideoDecoderId VideoDecoderId_VDA = mkid::id32base36_3<'V', 'D', 'A'>::value;
VideoDecoderId VideoDecoderId_VideoToolbox = mkid::id32base36_5<'V', 'T', 'B', 'o', 'x'>::value;
VideoDecoderId VideoDecoderId_MediaCodec = mkid::id32base36_4<'F','F','M','C'>::value;
VideoDecoderId VideoDecoderId_MMAL = mkid::id32base36_6<'F','F','M', 'M','A', 'L'>::value;
VideoDecoderId VideoDecoderId_QSV = mkid::id32base36_5<'F','F','Q','S', 'V'>::value;
VideoDecoderId VideoDecoderId_CrystalHD = mkid::id32base36_5<'F','F','C','H', 'D'>::value;

static void VideoDecoder_RegisterAll()
{
Expand Down Expand Up @@ -78,6 +81,7 @@ static void VideoDecoder_RegisterAll()
RegisterVideoDecoderCedarv_Man();
#endif //QTAV_HAVE(CEDARV)
}
// TODO: called in ::create()/next() etc. to ensure registered?
QVector<VideoDecoderId> VideoDecoder::registered()
{
VideoDecoder_RegisterAll();
Expand Down
67 changes: 66 additions & 1 deletion src/codec/video/VideoDecoderFFmpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/

#include "VideoDecoderFFmpegBase.h"
#include "QtAV/private/AVCompat.h"
#include "QtAV/private/factory.h"
Expand All @@ -39,6 +38,7 @@ class VideoDecoderFFmpeg : public VideoDecoderFFmpegBase
Q_OBJECT
DPTR_DECLARE_PRIVATE(VideoDecoderFFmpeg)
Q_PROPERTY(QString codecName READ codecName WRITE setCodecName NOTIFY codecNameChanged)
Q_PROPERTY(QString hwaccel READ hwaccel WRITE setHwaccel NOTIFY hwaccelChanged)
Q_PROPERTY(DiscardType skip_loop_filter READ skipLoopFilter WRITE setSkipLoopFilter)
Q_PROPERTY(DiscardType skip_idct READ skipIDCT WRITE setSkipIDCT)
// Force a strict standard compliance when encoding (accepted values: -2 to 2)
Expand Down Expand Up @@ -111,6 +111,34 @@ class VideoDecoderFFmpeg : public VideoDecoderFFmpegBase
};
Q_DECLARE_FLAGS(BugFlags, BugFlag)

static VideoDecoder* createMMAL() {
VideoDecoderFFmpeg *vd = new VideoDecoderFFmpeg();
vd->setProperty("hwaccel", "mmal");
return vd;
}
static VideoDecoder* createQSV() {
VideoDecoderFFmpeg *vd = new VideoDecoderFFmpeg();
vd->setProperty("hwaccel", "qsv");
return vd;
}
static VideoDecoder* createCrystalHD() {
VideoDecoderFFmpeg *vd = new VideoDecoderFFmpeg();
vd->setProperty("hwaccel", "crystalhd");
return vd;
}

static void registerHWA() {
#if defined(Q_OS_WIN32) || (defined(Q_OS_LINUX) && !defined(Q_PROCESSOR_ARM) && !defined(QT_ARCH_ARM))
VideoDecoder::Register(VideoDecoderId_QSV, createQSV, "QSV");
#endif
#ifdef Q_OS_LINUX
#if defined(Q_PROCESSOR_ARM)/*qt5*/ || defined(QT_ARCH_ARM) /*qt4*/
VideoDecoder::Register(VideoDecoderId_MMAL, createMMAL, "MMAL");
#else
VideoDecoder::Register(VideoDecoderId_CrystalHD, createCrystalHD, "CrystalHD");
#endif
#endif
}
VideoDecoderFFmpeg();
VideoDecoderId id() const Q_DECL_OVERRIDE Q_DECL_FINAL;
QString description() const Q_DECL_OVERRIDE Q_DECL_FINAL {
Expand Down Expand Up @@ -138,13 +166,28 @@ class VideoDecoderFFmpeg : public VideoDecoderFFmpegBase
MotionVectorVisFlags motionVectorVisFlags() const;
void setBugFlags(BugFlags value);
BugFlags bugFlags() const;
void setHwaccel(const QString& value);
QString hwaccel() const;
Q_SIGNALS:
void codecNameChanged() Q_DECL_OVERRIDE;
void hwaccelChanged();
};

extern VideoDecoderId VideoDecoderId_FFmpeg;
FACTORY_REGISTER(VideoDecoder, FFmpeg, "FFmpeg")

void RegisterFFmpegHWA_Man() {
VideoDecoderFFmpeg::registerHWA();
}

namespace {
static const struct factory_register_FFmpegHWA {
inline factory_register_FFmpegHWA() {
VideoDecoderFFmpeg::registerHWA();
}
} sInit_FFmpegHWA;
}

class VideoDecoderFFmpegPrivate Q_DECL_FINAL: public VideoDecoderFFmpegBasePrivate
{
public:
Expand Down Expand Up @@ -209,6 +252,7 @@ class VideoDecoderFFmpegPrivate Q_DECL_FINAL: public VideoDecoderFFmpegBasePriva
int threads;
int debug_mv;
int bug;
QString hwa;
};

VideoDecoderFFmpeg::VideoDecoderFFmpeg():
Expand All @@ -229,6 +273,13 @@ VideoDecoderFFmpeg::VideoDecoderFFmpeg():

VideoDecoderId VideoDecoderFFmpeg::id() const
{
DPTR_D(const VideoDecoderFFmpeg);
if (d.hwa == QLatin1String("mmal"))
return VideoDecoderId_MMAL;
if (d.hwa == QLatin1String("qsv"))
return VideoDecoderId_QSV;
if (d.hwa == QLatin1String("crystalhd"))
return VideoDecoderId_CrystalHD;
return VideoDecoderId_FFmpeg;
}

Expand Down Expand Up @@ -353,6 +404,20 @@ VideoDecoderFFmpeg::BugFlags VideoDecoderFFmpeg::bugFlags() const
return (BugFlags)d_func().bug;
}

void VideoDecoderFFmpeg::setHwaccel(const QString &value)
{
DPTR_D(VideoDecoderFFmpeg);
if (d.hwa == value)
return;
d.hwa = value.toLower();
Q_EMIT hwaccelChanged();
}

QString VideoDecoderFFmpeg::hwaccel() const
{
return d_func().hwa;
}

//namespace {
void i18n() {
QObject::tr("codecName");
Expand Down

0 comments on commit 7ac04eb

Please sign in to comment.