summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Hasselmann <michael.hasselmann@gmx.de>2018-05-05 13:58:23 +0200
committerMichael Hasselmann <michael.hasselmann@gmx.de>2018-05-05 14:19:53 +0200
commitea84bfbb96f3c9d4857ac9558e1a9de913d43df1 (patch)
tree6c940025566e52cc4b09b2baa24ab5027804f26f
parente5553b705b7355f513ff0cf892523a3799b5b41a (diff)
downloadmpv-examples-ea84bfbb96f3c9d4857ac9558e1a9de913d43df1.tar.bz2
mpv-examples-ea84bfbb96f3c9d4857ac9558e1a9de913d43df1.tar.xz
Convert QML example from opengl-cb to render API
Mimics the approach in SDL example.
-rw-r--r--libmpv/qml/main.cpp114
-rw-r--r--libmpv/qml/main.h13
2 files changed, 85 insertions, 42 deletions
diff --git a/libmpv/qml/main.cpp b/libmpv/qml/main.cpp
index 2122cd8..033c1af 100644
--- a/libmpv/qml/main.cpp
+++ b/libmpv/qml/main.cpp
@@ -13,49 +13,95 @@
#include <QtQuick/QQuickWindow>
#include <QtQuick/QQuickView>
+namespace
+{
+void on_mpv_events(void *ctx)
+{
+ Q_UNUSED(ctx)
+}
+
+void on_mpv_redraw(void *ctx)
+{
+ MpvObject::on_update(ctx);
+}
+
+static void *get_proc_address_mpv(void *ctx, const char *name)
+{
+ Q_UNUSED(ctx)
+
+ QOpenGLContext *glctx = QOpenGLContext::currentContext();
+ if (!glctx) return nullptr;
+
+ return reinterpret_cast<void *>(glctx->getProcAddress(QByteArray(name)));
+}
+
+}
+
class MpvRenderer : public QQuickFramebufferObject::Renderer
{
- static void *get_proc_address(void *ctx, const char *name) {
- (void)ctx;
- QOpenGLContext *glctx = QOpenGLContext::currentContext();
- if (!glctx)
- return NULL;
- return (void *)glctx->getProcAddress(QByteArray(name));
- }
+ MpvObject *obj;
- mpv::qt::Handle mpv;
- QQuickWindow *window;
- mpv_opengl_cb_context *mpv_gl;
public:
- MpvRenderer(const MpvObject *obj)
- : mpv(obj->mpv), window(obj->window()), mpv_gl(obj->mpv_gl)
+ MpvRenderer(MpvObject *new_obj)
+ : obj{new_obj}
{
- int r = mpv_opengl_cb_init_gl(mpv_gl, NULL, get_proc_address, NULL);
- if (r < 0)
- throw std::runtime_error("could not initialize OpenGL");
+ mpv_set_wakeup_callback(obj->mpv, on_mpv_events, nullptr);
}
virtual ~MpvRenderer()
+ {}
+
+ // This function is called when a new FBO is needed.
+ // This happens on the initial frame.
+ QOpenGLFramebufferObject * createFramebufferObject(const QSize &size)
{
- // Until this call is done, we need to make sure the player remains
- // alive. This is done implicitly with the mpv::qt::Handle instance
- // in this class.
- mpv_opengl_cb_uninit_gl(mpv_gl);
+ // init mpv_gl:
+ if (!obj->mpv_gl)
+ {
+ mpv_opengl_init_params gl_init_params{get_proc_address_mpv, nullptr, nullptr};
+ mpv_render_param params[]{
+ {MPV_RENDER_PARAM_API_TYPE, const_cast<char *>(MPV_RENDER_API_TYPE_OPENGL)},
+ {MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_init_params},
+ {MPV_RENDER_PARAM_INVALID, nullptr}
+ };
+
+ if (mpv_render_context_create(&obj->mpv_gl, obj->mpv, params) < 0)
+ throw std::runtime_error("failed to initialize mpv GL context");
+ mpv_render_context_set_update_callback(obj->mpv_gl, on_mpv_redraw, obj);
+ }
+
+ return QQuickFramebufferObject::Renderer::createFramebufferObject(size);
}
void render()
{
+ obj->window()->resetOpenGLState();
+
QOpenGLFramebufferObject *fbo = framebufferObject();
- window->resetOpenGLState();
- mpv_opengl_cb_draw(mpv_gl, fbo->handle(), fbo->width(), fbo->height());
- window->resetOpenGLState();
+ mpv_opengl_fbo mpfbo{.fbo = static_cast<int>(fbo->handle()), .w = fbo->width(), .h = fbo->height(), .internal_format = 0};
+ int flip_y{0};
+
+ mpv_render_param params[] = {
+ // Specify the default framebuffer (0) as target. This will
+ // render onto the entire screen. If you want to show the video
+ // in a smaller rectangle or apply fancy transformations, you'll
+ // need to render into a separate FBO and draw it manually.
+ {MPV_RENDER_PARAM_OPENGL_FBO, &mpfbo},
+ // Flip rendering (needed due to flipped GL coordinate system).
+ {MPV_RENDER_PARAM_FLIP_Y, &flip_y},
+ {MPV_RENDER_PARAM_INVALID, nullptr}
+ };
+ // See render_gl.h on what OpenGL environment mpv expects, and
+ // other API details.
+ mpv_render_context_render(obj->mpv_gl, params);
+
+ obj->window()->resetOpenGLState();
}
};
MpvObject::MpvObject(QQuickItem * parent)
- : QQuickFramebufferObject(parent), mpv_gl(0)
+ : QQuickFramebufferObject(parent), mpv{mpv_create()}, mpv_gl(nullptr)
{
- mpv = mpv::qt::Handle::FromRawHandle(mpv_create());
if (!mpv)
throw std::runtime_error("could not create mpv context");
@@ -65,27 +111,21 @@ MpvObject::MpvObject(QQuickItem * parent)
if (mpv_initialize(mpv) < 0)
throw std::runtime_error("could not initialize mpv context");
- // Make use of the MPV_SUB_API_OPENGL_CB API.
- mpv::qt::set_option_variant(mpv, "vo", "opengl-cb");
-
// Request hw decoding, just for testing.
mpv::qt::set_option_variant(mpv, "hwdec", "auto");
- // Setup the callback that will make QtQuick update and redraw if there
- // is a new video frame. Use a queued connection: this makes sure the
- // doUpdate() function is run on the GUI thread.
- mpv_gl = (mpv_opengl_cb_context *)mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB);
- if (!mpv_gl)
- throw std::runtime_error("OpenGL not compiled in");
- mpv_opengl_cb_set_update_callback(mpv_gl, MpvObject::on_update, (void *)this);
connect(this, &MpvObject::onUpdate, this, &MpvObject::doUpdate,
Qt::QueuedConnection);
}
MpvObject::~MpvObject()
{
- if (mpv_gl)
- mpv_opengl_cb_set_update_callback(mpv_gl, NULL, NULL);
+ if (mpv_gl) // only initialized if something got drawn
+ {
+ mpv_render_context_free(mpv_gl);
+ }
+
+ mpv_terminate_destroy(mpv);
}
void MpvObject::on_update(void *ctx)
@@ -114,7 +154,7 @@ QQuickFramebufferObject::Renderer *MpvObject::createRenderer() const
{
window()->setPersistentOpenGLContext(true);
window()->setPersistentSceneGraph(true);
- return new MpvRenderer(this);
+ return new MpvRenderer(const_cast<MpvObject *>(this));
}
int main(int argc, char **argv)
diff --git a/libmpv/qml/main.h b/libmpv/qml/main.h
index 9a65ae5..448707c 100644
--- a/libmpv/qml/main.h
+++ b/libmpv/qml/main.h
@@ -4,7 +4,7 @@
#include <QtQuick/QQuickFramebufferObject>
#include <mpv/client.h>
-#include <mpv/opengl_cb.h>
+#include <mpv/render_gl.h>
#include <mpv/qthelper.hpp>
class MpvRenderer;
@@ -13,24 +13,27 @@ class MpvObject : public QQuickFramebufferObject
{
Q_OBJECT
- mpv::qt::Handle mpv;
- mpv_opengl_cb_context *mpv_gl;
+ mpv_handle *mpv;
+ mpv_render_context *mpv_gl;
friend class MpvRenderer;
public:
+ static void on_update(void *ctx);
+
MpvObject(QQuickItem * parent = 0);
virtual ~MpvObject();
virtual Renderer *createRenderer() const;
+
public slots:
void command(const QVariant& params);
void setProperty(const QString& name, const QVariant& value);
+
signals:
void onUpdate();
+
private slots:
void doUpdate();
-private:
- static void on_update(void *ctx);
};
#endif