From 92dfda2e77348ade37eb07f1fed23dc46c74286f Mon Sep 17 00:00:00 2001 From: wang-bin Date: Fri, 10 May 2013 18:59:52 +0800 Subject: [PATCH] filterContextType, filter opacity. FilterContext in AVThread can be null TODO: do not check FilterContext in public api --- src/Filter.cpp | 22 ++++++++++++++++------ src/FilterContext.cpp | 6 ++++++ src/OSDFilter.cpp | 30 +++++++++++++++++++++++++++--- src/QPainterRenderer.cpp | 4 ++-- src/QtAV/Filter.h | 11 ++++++++--- src/QtAV/FilterContext.h | 11 ++++++++++- src/QtAV/OSDFilter.h | 7 +++++-- src/QtAV/private/AVThread_p.h | 3 ++- src/QtAV/private/Filter_p.h | 2 ++ src/VideoThread.cpp | 4 +--- 10 files changed, 79 insertions(+), 21 deletions(-) diff --git a/src/Filter.cpp b/src/Filter.cpp index bae43345..7ea06f23 100644 --- a/src/Filter.cpp +++ b/src/Filter.cpp @@ -40,12 +40,6 @@ void Filter::process(FilterContext *context, Statistics *statistics) Q_UNUSED(statistics); } -void Filter::process(QByteArray &data) -{ - Q_UNUSED(data); -} - - void Filter::setEnabled(bool enabled) { DPTR_D(Filter); @@ -58,4 +52,20 @@ bool Filter::isEnabled() const return d.enabled; } +void Filter::setOpacity(qreal o) +{ + DPTR_D(Filter); + d.opacity = o; +} + +qreal Filter::opacity() const +{ + return d_func().opacity; +} + +FilterContext::Type Filter::contextType() const +{ + return FilterContext::None; +} + } //namespace QtAV diff --git a/src/FilterContext.cpp b/src/FilterContext.cpp index 09ae2fcf..e74de949 100644 --- a/src/FilterContext.cpp +++ b/src/FilterContext.cpp @@ -46,6 +46,12 @@ VideoFilterContext::VideoFilterContext(): { } +QPainterFilterContext::QPainterFilterContext(): + painter(0) +{ + +} + FilterContext::Type QPainterFilterContext::type() const { return FilterContext::QtPainter; diff --git a/src/OSDFilter.cpp b/src/OSDFilter.cpp index 0406d297..8b4d808c 100644 --- a/src/OSDFilter.cpp +++ b/src/OSDFilter.cpp @@ -43,13 +43,31 @@ OSDFilterImpl::OSDFilterImpl(): } template<> -void OSFilterQPainter::process(FilterContext *context, Statistics *statistics) +void OSDFilterQPainter::process(FilterContext *context, Statistics *statistics) { if (mShowType == ShowNone) return; + if (!context || context->type() != contextType()) { + if (context && context->type() != contextType()) { + qDebug("incompatible context type"); + delete context; + context = 0; + } else { + qDebug("null context"); + } + context = FilterContext::create(FilterContext::QtPainter); + QPainterFilterContext* ctx = static_cast(context); + ctx->painter = new QPainter(); + } QPainterFilterContext* ctx = static_cast(context); - if (!ctx->painter) + if (!ctx->painter) { + //qWarning("null QPainter in OSDFilterQPainter!"); return; + } + if (!ctx->painter->isActive()) { + qWarning("QPainter in OSDFilterQPainter is not active"); + return; + } QPainter *p = ctx->painter; p->save(); //TODO: move outside? p->setFont(mFont); @@ -57,5 +75,11 @@ void OSFilterQPainter::process(FilterContext *context, Statistics *statistics) p->drawText(ctx->rect.topLeft(), text(statistics)); p->restore(); //TODO: move outside? } - +/* +template<> +FilterContext::Type OSDFilterQPainter::contextType() const +{ + return FilterContext::QtPainter; +} +*/ } //namespace QtAV diff --git a/src/QPainterRenderer.cpp b/src/QPainterRenderer.cpp index 4e5f4af7..f555b5f3 100644 --- a/src/QPainterRenderer.cpp +++ b/src/QPainterRenderer.cpp @@ -31,7 +31,7 @@ QPainterRenderer::QPainterRenderer() { DPTR_D(QPainterRenderer); d.filter_context = FilterContext::create(FilterContext::QtPainter); - d.osd_filter = new OSFilterQPainter(); + d.osd_filter = new OSDFilterQPainter(); d.filters.append(d.osd_filter); } @@ -39,7 +39,7 @@ QPainterRenderer::QPainterRenderer(QPainterRendererPrivate &d) :VideoRenderer(d) { d.filter_context = FilterContext::create(FilterContext::QtPainter); - d.osd_filter = new OSFilterQPainter(); + d.osd_filter = new OSDFilterQPainter(); d.filters.append(d.osd_filter); } diff --git a/src/QtAV/Filter.h b/src/QtAV/Filter.h index 9344cccc..d555d648 100644 --- a/src/QtAV/Filter.h +++ b/src/QtAV/Filter.h @@ -42,18 +42,23 @@ class Q_EXPORT Filter public: virtual ~Filter() = 0; //isEnabled() then setContext - virtual void process(FilterContext* context, Statistics* statistics); + /*! + * if context is null, or contextType() != context->type(), then create a right one and assign it to context. + */ + virtual void process(FilterContext *context, Statistics* statistics); //TODO: parameter FrameContext void setEnabled(bool enabled); //AVComponent.enabled bool isEnabled() const; - FilterContext::Type contextType() const; + qreal opacity() const; + void setOpacity(qreal o); + + virtual FilterContext::Type contextType() const; protected: /* * If the filter is in AVThread, it's safe to operate on ref. */ - virtual void process(QByteArray& data); Filter(FilterPrivate& d); friend class AVThread; diff --git a/src/QtAV/FilterContext.h b/src/QtAV/FilterContext.h index a406c02c..233d2b38 100644 --- a/src/QtAV/FilterContext.h +++ b/src/QtAV/FilterContext.h @@ -48,7 +48,7 @@ public: static FilterContext* create(Type t); virtual ~FilterContext(); virtual Type type() const = 0; - QByteArray data; + QByteArray data; //TODO: initialize() on data //QPainter, paintdevice, surface etc. contains all of them here? }; @@ -59,14 +59,23 @@ public: QRect rect; }; +//TODO: font, pen, brush etc? class Q_EXPORT QPainterFilterContext : public VideoFilterContext { public: + QPainterFilterContext(); QPainter *painter; virtual Type type() const; //QtPainter }; +template struct TypeTrait {}; +template<> struct TypeTrait { + enum { + type = FilterContext::QtPainter + }; +}; + } //namespace QtAV #endif // QTAV_FILTERCONTEXT_H diff --git a/src/QtAV/OSDFilter.h b/src/QtAV/OSDFilter.h index e66bf70a..ecc6c199 100644 --- a/src/QtAV/OSDFilter.h +++ b/src/QtAV/OSDFilter.h @@ -42,10 +42,13 @@ class OSDFilterImpl : public OSDFilter public: OSDFilterImpl(); ~OSDFilterImpl() {} - virtual void process(FilterContext* context, Statistics* statistics); + virtual void process(FilterContext *context, Statistics* statistics); + FilterContext::Type contextType() const { + return (FilterContext::Type)TypeTrait::type; + } }; -typedef OSDFilterImpl OSFilterQPainter; +typedef OSDFilterImpl OSDFilterQPainter; } //namespace QtAV diff --git a/src/QtAV/private/AVThread_p.h b/src/QtAV/private/AVThread_p.h index 4439051b..6a44afae 100644 --- a/src/QtAV/private/AVThread_p.h +++ b/src/QtAV/private/AVThread_p.h @@ -25,6 +25,7 @@ #include #include #include + #include #include @@ -67,7 +68,7 @@ public: QMutex mutex; QWaitCondition cond; //pause qreal delay; - FilterContext *filter_context; + FilterContext *filter_context;//TODO: use own smart ptr. QSharedPointer "=" is ugly QList filters; Statistics *statistics; //not obj. Statistics is unique for the player, which is in AVPlayer }; diff --git a/src/QtAV/private/Filter_p.h b/src/QtAV/private/Filter_p.h index e1c92e68..ec15a7a5 100644 --- a/src/QtAV/private/Filter_p.h +++ b/src/QtAV/private/Filter_p.h @@ -34,11 +34,13 @@ public: FilterPrivate(): enabled(true) , context(0) + , opacity(1) {} virtual ~FilterPrivate() {} bool enabled; FilterContext *context; //used only when is necessary + qreal opacity; }; } //namespace QtAV diff --git a/src/VideoThread.cpp b/src/VideoThread.cpp index 1740e96e..0e6e10a2 100644 --- a/src/VideoThread.cpp +++ b/src/VideoThread.cpp @@ -91,8 +91,6 @@ void VideoThread::run() Q_ASSERT(d.clock != 0); VideoDecoder *dec = static_cast(d.dec); VideoRenderer* vo = static_cast(d.writer); - //TODO: do not init filter_context - d.filter_context = FilterContext::create(FilterContext::QtPainter); //vo->filterContextType() while (!d.stop) { //TODO: why put it at the end of loop then playNextFrame() not work? if (tryPause()) { //DO NOT continue, or playNextFrame() will fail @@ -162,7 +160,7 @@ void VideoThread::run() if (!d.conv->convert(d.decoded_data.constData(), d.image.bits())) { }*/ QByteArray data = dec->data(); - if (d.statistics && d.filter_context) { + if (d.statistics) { d.statistics->video.current_time = QTime().addMSecs(int(pkt.pts * 1000.0)); //TODO: is it expensive? foreach (Filter *filter, d.filters) { filter->process(d.filter_context, d.statistics);