Skip to content

Commit

Permalink
filter: support x11/xv renderer
Browse files Browse the repository at this point in the history
have api changes. source compatible
  • Loading branch information
wang-bin committed Dec 1, 2015
1 parent f4cf8d4 commit 3a62151
Show file tree
Hide file tree
Showing 14 changed files with 94 additions and 60 deletions.
6 changes: 1 addition & 5 deletions examples/filters/SimpleFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,8 @@ void SimpleFilter::process(Statistics *statistics, VideoFrame *frame)
Q_UNUSED(frame);
if (!isEnabled())
return;
VideoFilterContext *ctx = static_cast<VideoFilterContext*>(context());
if (!ctx->painter)
return;

int t = mTime.elapsed()/100;

VideoFilterContext *ctx = static_cast<VideoFilterContext*>(context());
if (mCanRot) {
mMat.rotate(2, 0, 1, -0.1);
ctx->transform = mMat.toTransform();
Expand Down
4 changes: 3 additions & 1 deletion examples/filters/SimpleFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ class SimpleFilter : public VideoFilter
virtual ~SimpleFilter();
void enableRotate(bool r);
void enableWaveEffect(bool w);
virtual VideoFilterContext::Type contextType() const { return VideoFilterContext::QtPainter; }
bool isSupported(VideoFilterContext::Type ct) const {
return ct == VideoFilterContext::QtPainter || ct == VideoFilterContext::X11;
}
void setText(const QString& text);
QString text() const;
//show image if text is null
Expand Down
5 changes: 1 addition & 4 deletions examples/player/filters/OSDFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ void OSDFilter::process(Statistics *statistics, VideoFrame *frame)
Q_UNUSED(frame);
if (mShowType == ShowNone)
return;
QPainterFilterContext* ctx = static_cast<QPainterFilterContext*>(context());
if (!ctx)
return;
//qDebug("ctx=%p tid=%p main tid=%p", ctx, QThread::currentThread(), qApp->thread());
ctx->drawPlainText(ctx->rect, Qt::AlignCenter, text(statistics));
context()->drawPlainText(context()->rect, Qt::AlignCenter, text(statistics));
}
4 changes: 2 additions & 2 deletions examples/player/filters/OSDFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ class OSDFilter : public VideoFilter, public OSD
{
public:
OSDFilter(QObject *parent = 0);
VideoFilterContext::Type contextType() const {
return VideoFilterContext::QtPainter;
bool isSupported(VideoFilterContext::Type ct) const {
return ct == VideoFilterContext::QtPainter || ct == VideoFilterContext::X11;
}
protected:
void process(Statistics* statistics, VideoFrame* frame);
Expand Down
5 changes: 3 additions & 2 deletions src/QtAV/Filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ class Q_AV_EXPORT VideoFilter : public Filter
VideoFilter(QObject* parent = 0);

VideoFilterContext* context();
virtual VideoFilterContext::Type contextType() const;
QTAV_DEPRECATED virtual VideoFilterContext::Type contextType() const;
virtual bool isSupported(VideoFilterContext::Type ct) const;
bool installTo(AVPlayer *player);
/*
* filter.installTo(target,...) calls target.installFilter(filter)
Expand All @@ -97,7 +98,7 @@ class Q_AV_EXPORT VideoFilter : public Filter
* 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 prepareContext(VideoFilterContext *&context, Statistics* statistics, VideoFrame* frame = 0);
bool prepareContext(VideoFilterContext*& ctx, Statistics* statistics = 0, VideoFrame* frame = 0);
void apply(Statistics* statistics, VideoFrame *frame = 0);
protected:
VideoFilter(VideoFilterPrivate& d, QObject *parent = 0);
Expand Down
6 changes: 3 additions & 3 deletions src/QtAV/SubtitleFilter.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/******************************************************************************
QtAV: Media play library based on Qt and FFmpeg
Copyright (C) 2014 Wang Bin <[email protected]>
Copyright (C) 2014-2015 Wang Bin <[email protected]>
* This file is part of QtAV
Expand Down Expand Up @@ -61,8 +61,8 @@ class Q_AV_EXPORT SubtitleFilter : public VideoFilter, public SubtitleAPIProxy
public:
explicit SubtitleFilter(QObject *parent = 0);
void setPlayer(AVPlayer* player);
VideoFilterContext::Type contextType() const {
return VideoFilterContext::QtPainter;
bool isSupported(VideoFilterContext::Type ct) const Q_DECL_OVERRIDE {
return ct == VideoFilterContext::QtPainter || ct == VideoFilterContext::X11;
}
/*!
* \brief setFile
Expand Down
2 changes: 1 addition & 1 deletion src/QtAV/private/Filter_p.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/******************************************************************************
QtAV: Media play library based on Qt and FFmpeg
Copyright (C) 2013 Wang Bin <[email protected]>
Copyright (C) 2013-2015 Wang Bin <[email protected]>
* This file is part of QtAV
Expand Down
12 changes: 8 additions & 4 deletions src/VideoThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ class VideoThreadPrivate : public AVThreadPrivate
}
~VideoThreadPrivate() {
//not neccesary context is managed by filters.
filter_context = 0;
if (filter_context) {
delete filter_context;
filter_context = 0;
}
}

VideoFrameConverter conv;
Expand Down Expand Up @@ -190,8 +193,8 @@ void VideoThread::applyFilters(VideoFrame &frame)
VideoFilter *vf = static_cast<VideoFilter*>(filter);
if (!vf->isEnabled())
continue;
vf->prepareContext(d.filter_context, d.statistics, &frame);
vf->apply(d.statistics, &frame);
if (vf->prepareContext(d.filter_context, d.statistics, &frame))
vf->apply(d.statistics, &frame);
}
}
}
Expand Down Expand Up @@ -256,7 +259,7 @@ void VideoThread::run()
d.capture->setCaptureName(QFileInfo(d.statistics->url).completeBaseName());
}
//not neccesary context is managed by filters.
d.filter_context = 0;
d.filter_context = VideoFilterContext::create(VideoFilterContext::QtPainter);
VideoDecoder *dec = static_cast<VideoDecoder*>(d.dec);
Packet pkt;
QVariantHash *dec_opt = &d.dec_opt_normal; //TODO: restore old framedrop option after seek
Expand All @@ -282,6 +285,7 @@ void VideoThread::run()
bool skip_render = false; // keep true if decoded frame does not reach desired time
qreal v_a = 0;
int nb_no_pts = 0;
//bool wait_audio_drain
const char* pkt_data = NULL; // workaround for libav9 decode fail but error code >= 0
while (true) {
processNextTask();
Expand Down
54 changes: 36 additions & 18 deletions src/filter/Filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ VideoFilterContext *VideoFilter::context()
{
DPTR_D(VideoFilter);
if (!d.context) {
d.context = VideoFilterContext::create(contextType());
//fake. only to store some parameters at the beginnig. it will be destroyed and set to a new instance if context type mismatch in prepareContext, with old parameters
d.context = VideoFilterContext::create(VideoFilterContext::QtPainter);
}
return d.context;
}
Expand All @@ -122,6 +123,13 @@ VideoFilterContext::Type VideoFilter::contextType() const
return VideoFilterContext::None;
}

bool VideoFilter::isSupported(VideoFilterContext::Type ct) const
{
// TODO: return false
qDebug("VideoFilter::isSupported");
return contextType() == ct;
}

bool VideoFilter::installTo(AVPlayer *player)
{
return player->installFilter(this);
Expand All @@ -133,30 +141,40 @@ bool VideoFilter::installTo(AVOutput *output)
return output->installFilter(this);
}

//copy qpainter if context nut null
void VideoFilter::prepareContext(VideoFilterContext *&context, Statistics *statistics, VideoFrame* frame)
bool VideoFilter::prepareContext(VideoFilterContext *&ctx, Statistics *statistics, VideoFrame *frame)
{
if (contextType() != VideoFilterContext::QtPainter)
return;
DPTR_D(VideoFilter);
if (!d.context) {
d.context = VideoFilterContext::create(contextType());
d.context->video_width = statistics->video_only.width;
d.context->video_height = statistics->video_only.height;
if (!ctx || !isSupported(ctx->type())) {
//qDebug("no context: %p, or context type %d is not supported", ctx, ctx? ctx->type() : 0);
return false;
}
// TODO: reduce mem allocation
if (!context || context->type() != contextType()) {
if (context) {
delete context;
if (!d.context || d.context->type() != ctx->type()) {
VideoFilterContext* c = VideoFilterContext::create(ctx->type());//each filter has it's own context instance, but share the common parameters
if (d.context) {
c->pen = d.context->pen;
c->brush = d.context->brush;
c->clip_path = d.context->clip_path;
c->rect = d.context->rect;
c->transform = d.context->transform;
c->font = d.context->font;
c->opacity = d.context->opacity;
c->paint_device = d.context->paint_device;
}
if (d.context) {
delete d.context;
}
context = VideoFilterContext::create(contextType());
context->video_width = statistics->video_only.width;
context->video_height = statistics->video_only.height;
d.context = c;
}
d.context->video_width = statistics->video_only.width;
d.context->video_height = statistics->video_only.height;
ctx->video_width = statistics->video_only.width;
ctx->video_height = statistics->video_only.height;

// share common data
d.context->shareFrom(context);
d.context->shareFrom(ctx);
d.context->initializeOnFrame(frame);
context->shareFrom(d.context);
ctx->shareFrom(d.context);
return true;
}

void VideoFilter::apply(Statistics *statistics, VideoFrame *frame)
Expand Down
17 changes: 7 additions & 10 deletions src/filter/SubtitleFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,7 @@ void SubtitleFilter::process(Statistics *statistics, VideoFrame *frame)
Q_UNUSED(statistics);
Q_UNUSED(frame);
DPTR_D(SubtitleFilter);
QPainterFilterContext* ctx = static_cast<QPainterFilterContext*>(d.context);
if (!ctx)
return;
if (!ctx->paint_device) {
if (!context()->paint_device) {
qWarning("no paint device!");
return;
}
Expand All @@ -175,16 +172,16 @@ void SubtitleFilter::process(Statistics *statistics, VideoFrame *frame)
* if use renderer's resolution, we have to map bounding rect from video frame coordinate to renderer's
*/
//QImage img = d.player_sub->subtitle()->getImage(statistics->video_only.width, statistics->video_only.height, &rect);
QImage img = d.player_sub->subtitle()->getImage(ctx->paint_device->width(), ctx->paint_device->height(), &rect);
QImage img = d.player_sub->subtitle()->getImage(context()->paint_device->width(), context()->paint_device->height(), &rect);
if (img.isNull())
return;
ctx->drawImage(rect, img);
context()->drawImage(rect, img);
return;
}
ctx->font = d.font;
ctx->pen.setColor(d.color);
ctx->rect = d.realRect(ctx->paint_device->width(), ctx->paint_device->height());
ctx->drawPlainText(ctx->rect, Qt::AlignHCenter | Qt::AlignBottom, d.player_sub->subtitle()->getText());
context()->font = d.font;
context()->pen.setColor(d.color);
context()->rect = d.realRect(context()->paint_device->width(), context()->paint_device->height());
context()->drawPlainText(context()->rect, Qt::AlignHCenter | Qt::AlignBottom, d.player_sub->subtitle()->getText());
}

} //namespace QtAV
11 changes: 5 additions & 6 deletions src/filter/X11FilterContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,27 +195,26 @@ void X11FilterContext::drawPlainText(const QPointF &pos, const QString &text)

void X11FilterContext::drawPlainText(const QRectF &rect, int flags, const QString &text)
{
if (rect.isEmpty() || text.isEmpty())
if (text.isEmpty())
return;
if (rect.isEmpty()) {
drawPlainText(rect.topLeft(), text);
return;
}
if (test_img.size() != rect.size().toSize()) {
test_img = QImage(rect.size().toSize(), QImage::Format_ARGB32); //TODO: create once
}
painter->begin(&test_img);
prepare();
QRectF br = painter->boundingRect(rect, flags, text);
painter->end();
//qDebug() << br;
if (br.isEmpty())
return;

if (text == this->text && plain && mask_pix) {
renderTextImageX11(0, br.topLeft());
return;
}
if (rect.isNull()) {
drawPlainText(rect.topLeft(), text);
return;
}
this->text = text;
this->plain = true;

Expand Down
10 changes: 6 additions & 4 deletions src/output/video/VideoRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ void VideoRenderer::handlePaintEvent()
continue;
// qpainter on video frame always runs on video thread. qpainter on renderer's paint device can work on rendering thread
// Here apply filters on frame on video thread, for example, GPU filters
if (vf->contextType() == VideoFilterContext::QtPainter)
if (!vf->context() || vf->context()->type() != VideoFilterContext::OpenGL)
continue;
//vf->prepareContext(d.filter_context, d.statistics, 0);
vf->apply(d.statistics, &d.video_frame); //painter and paint device are ready, pass video frame is ok.
Expand Down Expand Up @@ -507,10 +507,12 @@ void VideoRenderer::handlePaintEvent()
if (!vf->isEnabled())
continue;
// qpainter rendering on renderer's paint device. only supported by none-null paint engine
if (vf->contextType() != VideoFilterContext::QtPainter)
if (!vf->context() || vf->context()->type() == VideoFilterContext::OpenGL) {
continue;
vf->prepareContext(d.filter_context, d.statistics, 0);
vf->apply(d.statistics, &d.video_frame); //painter and paint device are ready, pass video frame is ok.
}
if (vf->prepareContext(d.filter_context, d.statistics, 0)) {
vf->apply(d.statistics, &d.video_frame); //painter and paint device are ready, pass video frame is ok.
}
}
}
//end paint. how about QPainter::endNativePainting()?
Expand Down
9 changes: 9 additions & 0 deletions src/output/video/XVRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
*/
#include "QtAV/VideoRenderer.h"
#include "QtAV/private/VideoRenderer_p.h"
#include "QtAV/FilterContext.h"
#include <QWidget>
#include <QResizeEvent>
#include <QtCore/qmath.h>
Expand Down Expand Up @@ -225,6 +226,8 @@ class XVRendererPrivate : public VideoRendererPrivate
return false;
}
XSetBackground(display, gc, BlackPixel(display, DefaultScreen(display)));
if (filter_context)
((X11FilterContext*)filter_context)->resetX11((X11FilterContext::Display*)display, (X11FilterContext::GC)gc, (X11FilterContext::Drawable)q_func().winId());
return true;
}

Expand Down Expand Up @@ -349,6 +352,12 @@ XVRenderer::XVRenderer(QWidget *parent, Qt::WindowFlags f):
//setAttribute(Qt::WA_NoSystemBackground);
//setAutoFillBackground(false);
setAttribute(Qt::WA_PaintOnScreen, true);
d_func().filter_context = VideoFilterContext::create(VideoFilterContext::X11);
if (!d_func().filter_context) {
qWarning("No filter context for X11");
} else {
d_func().filter_context->paint_device = this;
}
}

bool XVRenderer::isSupported(VideoFormat::PixelFormat pixfmt) const
Expand Down
9 changes: 9 additions & 0 deletions widgets/X11Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
*/
#include "QtAV/VideoRenderer.h"
#include "QtAV/private/VideoRenderer_p.h"
#include "QtAV/FilterContext.h"
#include <QWidget>
#include <QResizeEvent>
#include <QtCore/qmath.h>
Expand Down Expand Up @@ -239,6 +240,8 @@ class X11RendererPrivate : public VideoRendererPrivate
return false;
}
XSetBackground(display, gc, BlackPixel(display, DefaultScreen(display)));
if (filter_context)
((X11FilterContext*)filter_context)->resetX11((X11FilterContext::Display*)display, (X11FilterContext::GC)gc, (X11FilterContext::Drawable)q_func().winId());
return true;
}
bool ensureImage(int w, int h) {
Expand Down Expand Up @@ -340,6 +343,12 @@ X11Renderer::X11Renderer(QWidget *parent, Qt::WindowFlags f):
//setAttribute(Qt::WA_NoSystemBackground);
//setAutoFillBackground(false);
setAttribute(Qt::WA_PaintOnScreen, true);
d_func().filter_context = VideoFilterContext::create(VideoFilterContext::X11);
if (!d_func().filter_context) {
qWarning("No filter context for X11");
} else {
d_func().filter_context->paint_device = this;
}
}

bool X11Renderer::isSupported(VideoFormat::PixelFormat pixfmt) const
Expand Down

0 comments on commit 3a62151

Please sign in to comment.