Ejemplo n.º 1
0
MpvWidget::MpvWidget(QWidget *parent, Qt::WindowFlags f)
    : QOpenGLWidget(parent, f)
{
    mpv = mpv::qt::Handle::FromRawHandle(mpv_create());
    if (!mpv)
        throw std::runtime_error("could not create mpv context");

    mpv_set_option_string(mpv, "terminal", "yes");
    mpv_set_option_string(mpv, "msg-level", "all=v");
    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");

    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, MpvWidget::on_update, (void *)this);
    connect(this, SIGNAL(frameSwapped()), SLOT(swapped()));

    mpv_observe_property(mpv, 0, "duration", MPV_FORMAT_DOUBLE);
    mpv_observe_property(mpv, 0, "time-pos", MPV_FORMAT_DOUBLE);
    mpv_set_wakeup_callback(mpv, wakeup, this);
}
Ejemplo n.º 2
0
VideoPlayer::~VideoPlayer()
{
    makeCurrent();
    if(mpv_gl)
        mpv_opengl_cb_set_update_callback(mpv_gl, nullptr, nullptr);
    mpv_opengl_cb_uninit_gl(mpv_gl);
}
Ejemplo n.º 3
0
VideoPlayer::VideoPlayer(QWidget *parent, Qt::WindowFlags f) :
    QOpenGLWidget(parent, f),
    //PosUpdateTimer(this)
    PosUpdate(mpv)
{
    mpv = mpv::qt::Handle::FromRawHandle(mpv_create());
    if(!mpv)
        throw std::runtime_error("could not create mpv context");

    //mpv_set_option_string(mpv, "terminal", "yes");
    //mpv_set_option_string(mpv, "msg-level", "all=v");

    if(mpv_initialize(mpv) < 0)
        throw std::runtime_error("could not initialize mpv context");

    mpv::qt::set_option_variant(mpv, "vo", "opengl-cb");

    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, VideoPlayer::on_update, (void*)this);
    connect(this, SIGNAL(frameSwapped()), SLOT(swapped()));

    //mpv_observe_property(mpv, 0, "time-pos", MPV_FORMAT_DOUBLE);
    mpv_set_wakeup_callback(mpv, wakeup, this);
    pause();
    TimePosition = 0;
    connect(&PosUpdate, SIGNAL(timeChanged(int)), this, SLOT(timeChange(int)));
    //connect(&PosUpdateTimer, SIGNAL(timeout()), this, SLOT(updateTime()));
    //PosUpdateTimer.start(40);
}
Ejemplo n.º 4
0
MpvWidget::~MpvWidget()
{
    makeCurrent();
    if (mpv_gl)
        mpv_opengl_cb_set_update_callback(mpv_gl, NULL, NULL);
    // 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);
}
Ejemplo n.º 5
0
void gmpv_mpv_obj_set_opengl_cb_callback(	GmpvMpvObj *mpv,
						mpv_opengl_cb_update_fn func,
						void *data )
{
	mpv->opengl_cb_callback = func;
	mpv->opengl_cb_callback_data = data;

	if(mpv->opengl_ctx)
	{
		mpv_opengl_cb_set_update_callback(mpv->opengl_ctx, func, data);
	}
}
void PlayerQuickItem::initMpv(PlayerComponent* player)
{
  m_mpv = player->getMpvHandle();

  m_mpvGL = (mpv_opengl_cb_context *)mpv_get_sub_api(m_mpv, MPV_SUB_API_OPENGL_CB);
  if (!m_mpvGL)
    throw FatalException(tr("OpenGL not enabled in libmpv."));

  mpv_opengl_cb_set_update_callback(m_mpvGL, on_update, (void *)this);

  connect(player, &PlayerComponent::windowVisible, this, &QQuickItem::setVisible);
  window()->update();
}
static void
finalise(GObject* obj)
{
    GtPlayerBackendMpvOpenGL* self = GT_PLAYER_BACKEND_MPV_OPENGL(obj);
    GtPlayerBackendMpvOpenGLPrivate* priv = gt_player_backend_mpv_opengl_get_instance_private(self);

    MESSAGE("Finalise");

    if (priv->mpv_event_cb_id > 0) g_source_remove(priv->mpv_event_cb_id);

    mpv_set_wakeup_callback(priv->mpv, NULL, NULL);
    mpv_opengl_cb_set_update_callback(priv->mpv_opengl, NULL, NULL);
    mpv_opengl_cb_uninit_gl(priv->mpv_opengl);
    mpv_terminate_destroy(priv->mpv);

    g_clear_object(&priv->widget);

    g_free(priv->uri);

    G_OBJECT_CLASS(gt_player_backend_mpv_opengl_parent_class)->finalize(obj);
}
Ejemplo n.º 8
0
static void
gt_player_mpv_init(GtPlayerMpv* self)
{
    GtPlayerMpvPrivate* priv = gt_player_mpv_get_instance_private(self);

    priv->mpv = mpv_create();
    priv->opengl_area = gtk_gl_area_new();
    priv->opengl_ready = FALSE;
    priv->chat_view = GTK_WIDGET(gt_chat_new());

    check_mpv_error(mpv_set_option_string(priv->mpv, "vo", "opengl-cb"));

    check_mpv_error(mpv_initialize(priv->mpv));

    priv->mpv_opengl = mpv_get_sub_api(priv->mpv, MPV_SUB_API_OPENGL_CB);

    mpv_opengl_cb_set_update_callback(priv->mpv_opengl, (mpv_opengl_cb_update_fn) opengl_cb, self);

    g_signal_connect(priv->opengl_area, "render", G_CALLBACK(render_cb), self);

    gtk_container_add(GTK_CONTAINER(self), priv->opengl_area);
    gtk_widget_show_all(GTK_WIDGET(self));
}
static void
gt_player_backend_mpv_opengl_init(GtPlayerBackendMpvOpenGL* self)
{
    GtPlayerBackendMpvOpenGLPrivate* priv = gt_player_backend_mpv_opengl_get_instance_private(self);

    MESSAGE("Init");

    setlocale(LC_NUMERIC, "C");

    priv->widget = gtk_gl_area_new();
    priv->mpv = mpv_create();

    g_object_set(priv->widget, "expand", TRUE, NULL);

    gtk_widget_add_events(priv->widget, GDK_BUTTON_PRESS_MASK);

    check_mpv_error(mpv_set_option_string(priv->mpv, "audio-client-name", "GNOME Twitch"));
    check_mpv_error(mpv_set_option_string(priv->mpv, "title", ""));
    check_mpv_error(mpv_set_option_string(priv->mpv, "vo", "opengl-cb"));
    check_mpv_error(mpv_set_option_string(priv->mpv, "softvol", "yes"));
    check_mpv_error(mpv_set_option_string(priv->mpv, "softvol-max", "100"));
    check_mpv_error(mpv_observe_property(priv->mpv, 0, "volume", MPV_FORMAT_DOUBLE));
    check_mpv_error(mpv_observe_property(priv->mpv, 0, "cache-buffering-state", MPV_FORMAT_INT64));

    check_mpv_error(mpv_initialize(priv->mpv));

    mpv_set_wakeup_callback(priv->mpv, mpv_wakeup_cb, self);

    priv->mpv_opengl = mpv_get_sub_api(priv->mpv, MPV_SUB_API_OPENGL_CB);

    mpv_opengl_cb_set_update_callback(priv->mpv_opengl, (mpv_opengl_cb_update_fn) opengl_cb, self);

    g_signal_connect(priv->widget, "destroy", G_CALLBACK(widget_destroy_cb), self);
    g_signal_connect(priv->widget, "realize", G_CALLBACK(realise_oneshot_cb), self);
    g_signal_connect(priv->widget, "render", G_CALLBACK(render_cb), self);
}
Ejemplo n.º 10
0
static void *render_thread_run(void *data) {
    struct render_thread *render_thread = data;

    EGLDisplay egl_display = NULL;
    EGLSurface egl_surface = NULL;
    EGLContext egl_context = NULL;
    // Gather egl params and bind to mpv opengl_cb
    {
        pthread_mutex_lock(&render_thread->lock);

        egl_display = render_thread->egl_display;
        egl_surface = render_thread->egl_surface;
        egl_context = render_thread->egl_context;

        eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
        eglSwapInterval(egl_display, 0);

        int res = mpv_opengl_cb_init_gl(render_thread->opengl_cb_context, NULL,
                                        mpv_get_proc_address, NULL);
        if (res < 0) {
            log_mpv_error("mpv_opengl_cb_init_gl failed", res);
        }

        mpv_opengl_cb_set_update_callback(render_thread->opengl_cb_context,
                                          update_callback, render_thread);

        // TODO: after the first uninit the video track is reset to 0 (none)
        // Setting this to 1 restarts the playback though and messes up the time the video
        // was playing at.
        uint64_t on = 1;
        mpv_set_property(render_thread->mpv, "vid", MPV_FORMAT_INT64, &on);

        render_thread->running = 1;
        pthread_cond_broadcast(&render_thread->ready);

        pthread_mutex_unlock(&render_thread->lock);
    }

    int64_t last_time = mpv_get_time_us(render_thread->mpv);
    int frames = 0;

    while (1) {
        // Wait for available frames
        {
            pthread_mutex_lock(&render_thread->frame_wait_lock);
            while (!render_thread->frame_available) {
                pthread_cond_wait(&render_thread->frame_wait, &render_thread->frame_wait_lock);
            }
            render_thread->frame_available = 0;
            pthread_mutex_unlock(&render_thread->frame_wait_lock);
        }

        // Check if still running
        int run, width, height;
        {
            pthread_mutex_lock(&render_thread->lock);
            run = render_thread->running;
            width = render_thread->width;
            height = render_thread->height;
            pthread_mutex_unlock(&render_thread->lock);
        }
        if (!run) {
            break;
        }

//        int64_t draw_start = mpv_get_time_us(render_thread->mpv);
        mpv_opengl_cb_draw(render_thread->opengl_cb_context, 0, width, -height);
//        LOGI("Render time %ld", (mpv_get_time_us(render_thread->mpv) - draw_start));
        if (!eglSwapBuffers(egl_display, egl_surface)) {
            LOGE("eglSwapBuffers failed %d", eglGetError());
        }
//        mpv_opengl_cb_report_flip(render_thread->opengl_cb_context, 0);

        frames++;

        int64_t now = mpv_get_time_us(render_thread->mpv);
        if (now - last_time >= 1000 * 1000) {
            // last_time += 1000 * 1000;
            last_time = now; // Don't play catch-up
            LOGI("Render fps %d", frames);
            frames = 0;
        }
    }

    // Release egl params and unbind from mpv opengl_cb
    {
        pthread_mutex_lock(&render_thread->lock);

        int res = mpv_opengl_cb_uninit_gl(render_thread->opengl_cb_context);
        if (res < 0) {
            log_mpv_error("mpv_opengl_cb_uninit_gl failed", res);
        }

        eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);

        pthread_mutex_unlock(&render_thread->lock);
    }

    return NULL;
}
Ejemplo n.º 11
0
PlayerQuickItem::~PlayerQuickItem()
{
  if (m_mpvGL)
    mpv_opengl_cb_set_update_callback(m_mpvGL, NULL, NULL);
}