File indexing completed on 2024-05-19 04:45:39
0001 /* 0002 * SPDX-FileCopyrightText: 2023 George Florea Bănuș <georgefb899@gmail.com> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include "mpvrenderer.h" 0008 #include "mpvabstractitem.h" 0009 #include "mpvabstractitem_p.h" 0010 #include "mpvcontroller.h" 0011 0012 #include <QGuiApplication> 0013 #include <QOpenGLContext> 0014 #include <QOpenGLFramebufferObject> 0015 #include <QQuickWindow> 0016 0017 static void *get_proc_address_mpv(void *ctx, const char *name) 0018 { 0019 Q_UNUSED(ctx) 0020 0021 QOpenGLContext *glctx = QOpenGLContext::currentContext(); 0022 if (!glctx) { 0023 return nullptr; 0024 } 0025 0026 return reinterpret_cast<void *>(glctx->getProcAddress(QByteArray(name))); 0027 } 0028 0029 void on_mpv_redraw(void *ctx) 0030 { 0031 QMetaObject::invokeMethod(static_cast<MpvAbstractItem *>(ctx), &MpvAbstractItem::update, Qt::QueuedConnection); 0032 } 0033 0034 MpvRenderer::MpvRenderer(MpvAbstractItem *new_obj) 0035 : m_mpvAItem{new_obj} 0036 { 0037 m_mpvAItem->window()->setPersistentSceneGraph(true); 0038 } 0039 0040 void MpvRenderer::render() 0041 { 0042 QOpenGLFramebufferObject *fbo = framebufferObject(); 0043 mpv_opengl_fbo mpfbo; 0044 mpfbo.fbo = static_cast<int>(fbo->handle()); 0045 mpfbo.w = fbo->width(); 0046 mpfbo.h = fbo->height(); 0047 mpfbo.internal_format = 0; 0048 0049 int flip_y{0}; 0050 0051 mpv_render_param params[] = {// Specify the default framebuffer (0) as target. This will 0052 // render onto the entire screen. If you want to show the video 0053 // in a smaller rectangle or apply fancy transformations, you'll 0054 // need to render into a separate FBO and draw it manually. 0055 {MPV_RENDER_PARAM_OPENGL_FBO, &mpfbo}, 0056 {MPV_RENDER_PARAM_FLIP_Y, &flip_y}, 0057 {MPV_RENDER_PARAM_INVALID, nullptr}}; 0058 // See render_gl.h on what OpenGL environment mpv expects, and 0059 // other API details. 0060 mpv_render_context_render(m_mpvAItem->d_ptr->m_mpv_gl, params); 0061 } 0062 0063 QOpenGLFramebufferObject *MpvRenderer::createFramebufferObject(const QSize &size) 0064 { 0065 // init mpv_gl: 0066 if (!m_mpvAItem->d_ptr->m_mpv_gl) { 0067 #if MPV_CLIENT_API_VERSION < MPV_MAKE_VERSION(2, 0) 0068 mpv_opengl_init_params gl_init_params{get_proc_address_mpv, nullptr, nullptr}; 0069 #else 0070 mpv_opengl_init_params gl_init_params{get_proc_address_mpv, nullptr}; 0071 #endif 0072 0073 mpv_render_param display{MPV_RENDER_PARAM_INVALID, nullptr}; 0074 #if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) 0075 if (QGuiApplication::platformName() == QStringLiteral("xcb")) { 0076 display.type = MPV_RENDER_PARAM_X11_DISPLAY; 0077 display.data = qGuiApp->nativeInterface<QNativeInterface::QX11Application>()->display(); 0078 } 0079 0080 if (QGuiApplication::platformName() == QStringLiteral("wayland")) { 0081 display.type = MPV_RENDER_PARAM_WL_DISPLAY; 0082 display.data = qGuiApp->nativeInterface<QNativeInterface::QWaylandApplication>()->display(); 0083 } 0084 #endif 0085 mpv_render_param params[]{{MPV_RENDER_PARAM_API_TYPE, const_cast<char *>(MPV_RENDER_API_TYPE_OPENGL)}, 0086 {MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_init_params}, 0087 display, 0088 {MPV_RENDER_PARAM_INVALID, nullptr}}; 0089 0090 int result = mpv_render_context_create(&m_mpvAItem->d_ptr->m_mpv_gl, m_mpvAItem->d_ptr->m_mpv, params); 0091 if (result < 0) { 0092 qFatal("failed to initialize mpv GL context"); 0093 } 0094 0095 mpv_render_context_set_update_callback(m_mpvAItem->d_ptr->m_mpv_gl, on_mpv_redraw, m_mpvAItem); 0096 Q_EMIT m_mpvAItem->ready(); 0097 } 0098 0099 return QQuickFramebufferObject::Renderer::createFramebufferObject(size); 0100 }