VideoPlayer::~VideoPlayer() { makeCurrent(); if(mpv_gl) mpv_opengl_cb_set_update_callback(mpv_gl, nullptr, nullptr); mpv_opengl_cb_uninit_gl(mpv_gl); }
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); }
static void finalise(GObject* obj) { GtPlayerMpv* self = GT_PLAYER_MPV(obj); GtPlayerMpvPrivate* priv = gt_player_mpv_get_instance_private(self); gtk_gl_area_make_current(GTK_GL_AREA(priv->opengl_area)); mpv_opengl_cb_uninit_gl(priv->mpv_opengl); G_OBJECT_CLASS(gt_player_mpv_parent_class)->finalize(obj); }
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); }
void gmpv_mpv_obj_quit(GmpvMpvObj *mpv) { g_info("Terminating mpv"); if(mpv->tmp_input_file) { g_unlink(mpv->tmp_input_file); } if(mpv->opengl_ctx) { g_debug("Uninitializing opengl-cb"); mpv_opengl_cb_uninit_gl(mpv->opengl_ctx); mpv->opengl_ctx = NULL; } g_assert(mpv->mpv_ctx); mpv_terminate_destroy(mpv->mpv_ctx); mpv->mpv_ctx = NULL; }
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; }
PlayerRenderer::~PlayerRenderer() { // Keep in mind that the m_mpv handle must be held until this is done. if (m_mpvGL) mpv_opengl_cb_uninit_gl(m_mpvGL); }