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:
wang-bin
2013-05-11 14:20:35 +08:00
parent d5a1605d57
commit ed1ff780ad
9 changed files with 123 additions and 39 deletions
+4 -8
View File
@@ -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
View File
@@ -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)
+48
View File
@@ -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
View File
@@ -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
View File
@@ -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)
};
+17 -1
View File
@@ -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);
};
+4 -2
View File
@@ -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;
+3
View File
@@ -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
View File
@@ -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);
}
}
}