mirror of
https://github.com/wang-bin/QtAV.git
synced 2026-10-29 03:26:39 +08:00
use internal context if context type is wrong or no context
TODO: filters need to manager their contexts, which sometimes are shared by multiple filters. so shall we use smart ptr, like RefCount?
This commit is contained in:
+4
-8
@@ -37,10 +37,8 @@ AVThreadPrivate::~AVThreadPrivate() {
|
||||
}
|
||||
packets.setBlocking(true); //???
|
||||
packets.clear();
|
||||
if (filter_context) {
|
||||
delete filter_context; //TODO: need it?
|
||||
filter_context = 0;
|
||||
}
|
||||
//not neccesary context is managed by filters.
|
||||
filter_context = 0;
|
||||
qDeleteAll(filters); //TODO: is it safe?
|
||||
filters.clear();
|
||||
}
|
||||
@@ -147,10 +145,8 @@ void AVThread::resetState()
|
||||
d.demux_end = false;
|
||||
d.packets.setBlocking(true);
|
||||
d.packets.clear();
|
||||
if (d.filter_context) {
|
||||
delete d.filter_context;
|
||||
d.filter_context = 0;
|
||||
}
|
||||
//not neccesary context is managed by filters.
|
||||
d.filter_context = 0;
|
||||
}
|
||||
|
||||
bool AVThread::tryPause()
|
||||
|
||||
+29
-3
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "QtAV/Filter.h"
|
||||
#include "private/Filter_p.h"
|
||||
#include "QtAV/Statistics.h"
|
||||
|
||||
namespace QtAV {
|
||||
|
||||
@@ -34,10 +35,35 @@ Filter::~Filter()
|
||||
{
|
||||
}
|
||||
|
||||
void Filter::process(FilterContext *context, Statistics *statistics)
|
||||
void Filter::process(FilterContext *&context, Statistics *statistics, QByteArray* data)
|
||||
{
|
||||
Q_UNUSED(context);
|
||||
Q_UNUSED(statistics);
|
||||
DPTR_D(Filter);
|
||||
if(context)
|
||||
context->type();
|
||||
if (!context || context->type() != contextType()) {
|
||||
if (context) {
|
||||
qDebug("incompatible context type");
|
||||
//we don't delete it because the context MUST be used by other filters
|
||||
//TODO: How to release them at the end? refcount?
|
||||
} else {
|
||||
qDebug("null context");
|
||||
}
|
||||
//use internal context
|
||||
if (d.context) {
|
||||
qDebug("replace context with internal one");
|
||||
context = d.context;
|
||||
} else {
|
||||
context = FilterContext::create(contextType());
|
||||
qDebug("new filter context=%p, type=%d", context, contextType());
|
||||
context->video_width = statistics->video_only.width;
|
||||
context->video_height = statistics->video_only.height;
|
||||
}
|
||||
}
|
||||
if (data)
|
||||
context->initializeOnData(data);
|
||||
d.context = context;
|
||||
d.statistics = statistics;
|
||||
process();
|
||||
}
|
||||
|
||||
void Filter::setEnabled(bool enabled)
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "QtAV/FilterContext.h"
|
||||
#include <QtGui/QImage>
|
||||
#include <QtGui/QPainter>
|
||||
|
||||
namespace QtAV {
|
||||
|
||||
@@ -36,10 +38,21 @@ FilterContext* FilterContext::create(Type t)
|
||||
return ctx;
|
||||
}
|
||||
|
||||
FilterContext::FilterContext():
|
||||
video_width(0)
|
||||
, video_height(0)
|
||||
{
|
||||
}
|
||||
|
||||
FilterContext::~FilterContext()
|
||||
{
|
||||
}
|
||||
|
||||
void FilterContext::initializeOnData(QByteArray *data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
qDebug("%s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
VideoFilterContext::VideoFilterContext():
|
||||
rect(32, 32, 0, 0)
|
||||
@@ -48,8 +61,23 @@ VideoFilterContext::VideoFilterContext():
|
||||
|
||||
QPainterFilterContext::QPainterFilterContext():
|
||||
painter(0)
|
||||
, paint_device(0)
|
||||
{
|
||||
}
|
||||
|
||||
QPainterFilterContext::~QPainterFilterContext()
|
||||
{
|
||||
if (paint_device) {
|
||||
if (painter) { //painter may assigned by vo
|
||||
painter->end();
|
||||
qDebug("delete painter");
|
||||
delete painter;
|
||||
painter = 0;
|
||||
}
|
||||
qDebug("delete paint device");
|
||||
delete paint_device;
|
||||
paint_device = 0;
|
||||
}
|
||||
}
|
||||
|
||||
FilterContext::Type QPainterFilterContext::type() const
|
||||
@@ -57,5 +85,25 @@ FilterContext::Type QPainterFilterContext::type() const
|
||||
return FilterContext::QtPainter;
|
||||
}
|
||||
|
||||
void QPainterFilterContext::initializeOnData(QByteArray *data)
|
||||
{
|
||||
Q_ASSERT(video_width > 0 && video_height > 0);
|
||||
if (!data)
|
||||
return;
|
||||
if (data->isEmpty())
|
||||
return;
|
||||
if (paint_device) {
|
||||
if (painter) {
|
||||
painter->end(); //destroy a paint device that is being painted is not allowed!
|
||||
}
|
||||
delete paint_device;
|
||||
paint_device = 0;
|
||||
}
|
||||
paint_device = new QImage((uchar*)data->data(), video_width, video_height, QImage::Format_RGB32);
|
||||
if (!painter)
|
||||
painter = new QPainter();
|
||||
painter->begin((QImage*)paint_device);
|
||||
}
|
||||
|
||||
|
||||
} //namespace QtAV
|
||||
|
||||
+6
-16
@@ -43,25 +43,15 @@ OSDFilterImpl<QPainterFilterContext>::OSDFilterImpl():
|
||||
}
|
||||
|
||||
template<>
|
||||
void OSDFilterQPainter::process(FilterContext *context, Statistics *statistics)
|
||||
void OSDFilterQPainter::process()
|
||||
{
|
||||
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<QPainterFilterContext*>(context);
|
||||
ctx->painter = new QPainter();
|
||||
}
|
||||
QPainterFilterContext* ctx = static_cast<QPainterFilterContext*>(context);
|
||||
DPTR_D(Filter);
|
||||
QPainterFilterContext* ctx = static_cast<QPainterFilterContext*>(d.context);
|
||||
//qDebug("ctx=%p tid=%p main tid=%p", ctx, QThread::currentThread(), qApp->thread());
|
||||
if (!ctx->painter) {
|
||||
//qWarning("null QPainter in OSDFilterQPainter!");
|
||||
qWarning("null QPainter in OSDFilterQPainter!");
|
||||
return;
|
||||
}
|
||||
if (!ctx->painter->isActive()) {
|
||||
@@ -72,7 +62,7 @@ void OSDFilterQPainter::process(FilterContext *context, Statistics *statistics)
|
||||
p->save(); //TODO: move outside?
|
||||
p->setFont(mFont);
|
||||
p->setPen(Qt::white);
|
||||
p->drawText(ctx->rect.topLeft(), text(statistics));
|
||||
p->drawText(ctx->rect.topLeft(), text(d.statistics));
|
||||
p->restore(); //TODO: move outside?
|
||||
}
|
||||
/*
|
||||
|
||||
+8
-7
@@ -40,12 +40,8 @@ class Q_EXPORT Filter
|
||||
{
|
||||
DPTR_DECLARE_PRIVATE(Filter)
|
||||
public:
|
||||
virtual ~Filter() = 0;
|
||||
virtual ~Filter();
|
||||
//isEnabled() then setContext
|
||||
/*!
|
||||
* 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;
|
||||
@@ -55,14 +51,19 @@ public:
|
||||
|
||||
virtual FilterContext::Type contextType() const;
|
||||
|
||||
/*!
|
||||
* check context and apply the filter
|
||||
* if context is null, or contextType() != context->type(), then create a right one and assign it to context.
|
||||
*/
|
||||
void process(FilterContext *&context, Statistics* statistics, QByteArray* data = 0);
|
||||
|
||||
protected:
|
||||
/*
|
||||
* If the filter is in AVThread, it's safe to operate on ref.
|
||||
*/
|
||||
Filter(FilterPrivate& d);
|
||||
virtual void process() = 0;
|
||||
|
||||
friend class AVThread;
|
||||
friend class VideoThread;
|
||||
DPTR_DECLARE(Filter)
|
||||
};
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
*/
|
||||
|
||||
class QPainter;
|
||||
class QPaintDevice;
|
||||
namespace QtAV {
|
||||
|
||||
class FilterContext;
|
||||
@@ -46,10 +47,16 @@ public:
|
||||
None
|
||||
};
|
||||
static FilterContext* create(Type t);
|
||||
|
||||
FilterContext();
|
||||
virtual ~FilterContext();
|
||||
virtual Type type() const = 0;
|
||||
QByteArray data; //TODO: initialize() on data
|
||||
//TODO: how to move them to VideoFilterContext?
|
||||
int video_width, video_height; //original size
|
||||
//QPainter, paintdevice, surface etc. contains all of them here?
|
||||
protected:
|
||||
virtual void initializeOnData(QByteArray *data); //private?
|
||||
friend class Filter;
|
||||
};
|
||||
|
||||
class Q_EXPORT VideoFilterContext : public FilterContext
|
||||
@@ -64,8 +71,17 @@ class Q_EXPORT QPainterFilterContext : public VideoFilterContext
|
||||
{
|
||||
public:
|
||||
QPainterFilterContext();
|
||||
virtual ~QPainterFilterContext();
|
||||
|
||||
QPainter *painter;
|
||||
/*
|
||||
* for the filters apply on decoded data, paint_device must be initialized once the data changes
|
||||
* can we allocate memory on stack?
|
||||
*/
|
||||
QPaintDevice *paint_device;
|
||||
virtual Type type() const; //QtPainter
|
||||
protected:
|
||||
virtual void initializeOnData(QByteArray* data);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -31,21 +31,23 @@ class OSDFilterPrivate;
|
||||
//TODO: not template. OSDFilter : public Filter, public OSD
|
||||
class OSDFilter : public Filter, public OSD
|
||||
{
|
||||
DPTR_DECLARE_PRIVATE(OSDFilter)
|
||||
protected:
|
||||
DPTR_DECLARE_PRIVATE(OSDFilter)
|
||||
OSDFilter(OSDFilterPrivate& d);
|
||||
};
|
||||
|
||||
template<class Context>
|
||||
class OSDFilterImpl : public OSDFilter
|
||||
{
|
||||
//DPTR_DECLARE_PRIVATE(OSDFilterImpl<Context>)
|
||||
public:
|
||||
OSDFilterImpl();
|
||||
~OSDFilterImpl() {}
|
||||
virtual void process(FilterContext *context, Statistics* statistics);
|
||||
FilterContext::Type contextType() const {
|
||||
return (FilterContext::Type)TypeTrait<Context>::type;
|
||||
}
|
||||
protected:
|
||||
virtual void process();
|
||||
};
|
||||
|
||||
typedef OSDFilterImpl<QPainterFilterContext> OSDFilterQPainter;
|
||||
|
||||
@@ -28,18 +28,21 @@ namespace QtAV {
|
||||
|
||||
class Filter;
|
||||
class FilterContext;
|
||||
class Statistics;
|
||||
class FilterPrivate : public DPtrPrivate<Filter>
|
||||
{
|
||||
public:
|
||||
FilterPrivate():
|
||||
enabled(true)
|
||||
, context(0)
|
||||
, statistics(0)
|
||||
, opacity(1)
|
||||
{}
|
||||
virtual ~FilterPrivate() {}
|
||||
|
||||
bool enabled;
|
||||
FilterContext *context; //used only when is necessary
|
||||
Statistics *statistics;
|
||||
qreal opacity;
|
||||
};
|
||||
|
||||
|
||||
+4
-2
@@ -162,8 +162,10 @@ void VideoThread::run()
|
||||
QByteArray data = dec->data();
|
||||
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);
|
||||
if (!d.filters.isEmpty()) {
|
||||
foreach (Filter *filter, d.filters) {
|
||||
filter->process(d.filter_context, d.statistics, &data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user