diff options
-rw-r--r-- | include/VideoPlayer.hpp | 11 | ||||
-rw-r--r-- | src/VideoPlayer.cpp | 92 |
2 files changed, 70 insertions, 33 deletions
diff --git a/include/VideoPlayer.hpp b/include/VideoPlayer.hpp index c52c1e5..6bd8f4f 100644 --- a/include/VideoPlayer.hpp +++ b/include/VideoPlayer.hpp @@ -12,7 +12,7 @@ #include <functional> class mpv_handle; -class mpv_opengl_cb_context; +class mpv_render_context; namespace QuickMedia { class VideoInitializationException : public std::runtime_error { @@ -35,12 +35,15 @@ namespace QuickMedia { // @path can also be an url if youtube-dl is installed void load_file(const std::string &path); - // This counter is incremented when mpv wants to redraw content - std::atomic_int redrawCounter; + // This is updated when mpv wants to render + std::atomic_bool redraw; + std::atomic_bool event_update; PlaybackEndedCallback onPlaybackEndedCallback; private: + void handle_events(); + private: mpv_handle *mpv; - mpv_opengl_cb_context *mpvGl; + mpv_render_context *mpvGl; std::unique_ptr<sf::Context> context; sf::Sprite sprite; sf::Texture texture; diff --git a/src/VideoPlayer.cpp b/src/VideoPlayer.cpp index bcc419c..0e6b391 100644 --- a/src/VideoPlayer.cpp +++ b/src/VideoPlayer.cpp @@ -1,7 +1,7 @@ #include "../include/VideoPlayer.hpp" #include <SFML/Window/Mouse.hpp> #include <mpv/client.h> -#include <mpv/opengl_cb.h> +#include <mpv/render_gl.h> #include <SFML/OpenGL.hpp> #include <clocale> #include <cmath> @@ -11,9 +11,14 @@ namespace QuickMedia { return (void*)sf::Context::getFunction(name); } - static void onMpvRedraw(void *rawVideo) { - VideoPlayer *video_player = (VideoPlayer*)rawVideo; - ++video_player->redrawCounter; + static void onMpvRedraw(void *ctx) { + VideoPlayer *video_player = (VideoPlayer*)ctx; + video_player->redraw = true; + } + + static void on_mpv_events(void *ctx) { + VideoPlayer *video_player = (VideoPlayer*)ctx; + video_player->event_update = true; } static void check_error(int status) { @@ -31,7 +36,8 @@ namespace QuickMedia { } VideoPlayer::VideoPlayer(unsigned int width, unsigned int height, sf::WindowHandle window_handle, const char *file, bool loop) : - redrawCounter(0), + redraw(false), + event_update(false), onPlaybackEndedCallback(nullptr), mpv(nullptr), mpvGl(nullptr), @@ -66,13 +72,24 @@ namespace QuickMedia { if(loop) check_error(mpv_set_option_string(mpv, "loop", "inf")); - mpvGl = (mpv_opengl_cb_context*)mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB); - if(!mpvGl) - throw VideoInitializationException("Failed to initialize mpv opengl render context"); + //mpvGl = (mpv_opengl_cb_context*)mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB); + //if(!mpvGl) + // throw VideoInitializationException("Failed to initialize mpv opengl render context"); + + mpv_opengl_init_params opengl_init_params; + opengl_init_params.get_proc_address = getProcAddressMpv; + opengl_init_params.get_proc_address_ctx = nullptr; + mpv_render_param params[] = { + { MPV_RENDER_PARAM_API_TYPE, (void*)MPV_RENDER_API_TYPE_OPENGL }, + { MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &opengl_init_params }, + { (mpv_render_param_type)0, nullptr } + }; + + if (mpv_render_context_create(&mpvGl, mpv, params) < 0) + throw VideoInitializationException("failed to initialize mpv GL context"); - mpv_opengl_cb_set_update_callback(mpvGl, onMpvRedraw, this); - if(mpv_opengl_cb_init_gl(mpvGl, nullptr, getProcAddressMpv, nullptr) < 0) - throw VideoInitializationException("Failed to initialize mpv gl callback func"); + mpv_render_context_set_update_callback(mpvGl, onMpvRedraw, this); + mpv_set_wakeup_callback(mpv, on_mpv_events, this); context->setActive(false); @@ -83,10 +100,9 @@ namespace QuickMedia { VideoPlayer::~VideoPlayer() { if(mpvGl) - mpv_opengl_cb_set_update_callback(mpvGl, nullptr, nullptr); - + + mpv_render_context_free(mpvGl); free(textureBuffer); - mpv_opengl_cb_uninit_gl(mpvGl); mpv_detach_destroy(mpv); } @@ -127,8 +143,8 @@ namespace QuickMedia { image_size.y *= image_scale.y; sprite.setPosition(std::floor(desired_size.x * 0.5f - image_size.x * 0.5f), std::floor(desired_size.y * 0.5f - image_size.y * 0.5f)); } - - void VideoPlayer::draw(sf::RenderWindow &window) { + + void VideoPlayer::handle_events() { while(true) { mpv_event *mpvEvent = mpv_wait_event(mpv, 0.0); if(mpvEvent->event_id == MPV_EVENT_NONE) @@ -160,22 +176,40 @@ namespace QuickMedia { if(onPlaybackEndedCallback) onPlaybackEndedCallback(); } else { - //printf("Mpv event: %s\n", mpv_event_name(mpvEvent->event_id)); + printf("Mpv event: %s\n", mpv_event_name(mpvEvent->event_id)); } } + } + + void VideoPlayer::draw(sf::RenderWindow &window) { + bool do_event_update = event_update.exchange(false); + if(do_event_update) + handle_events(); - if(redrawCounter > 0 && textureBuffer) { - --redrawCounter; - auto textureSize = texture.getSize(); - context->setActive(true); - //mpv_render_context_render(mpvGl, params); - mpv_opengl_cb_draw(mpvGl, 0, textureSize.x, textureSize.y); - // TODO: Instead of copying video to cpu buffer and then to texture, copy directly from video buffer to texture buffer - glReadPixels(0, 0, textureSize.x, textureSize.y, GL_RGBA, GL_UNSIGNED_BYTE, textureBuffer); - texture.update(textureBuffer); - sprite.setTexture(texture, true); - mpv_opengl_cb_report_flip(mpvGl, 0); - context->setActive(false); + if(textureBuffer && redraw) { + uint64_t update_flags = mpv_render_context_update(mpvGl); + if((update_flags & MPV_RENDER_UPDATE_FRAME) && redraw.exchange(false)) { + auto textureSize = texture.getSize(); + + mpv_opengl_fbo opengl_fbo; + opengl_fbo.fbo = 0; + opengl_fbo.w = textureSize.x; + opengl_fbo.h = textureSize.y; + opengl_fbo.internal_format = 0; + mpv_render_param params[] = + { + { MPV_RENDER_PARAM_OPENGL_FBO, &opengl_fbo }, + { (mpv_render_param_type)0, nullptr } + }; + + context->setActive(true); + mpv_render_context_render(mpvGl, params); + // TODO: Instead of copying video to cpu buffer and then to texture, copy directly from video buffer to texture buffer + glReadPixels(0, 0, textureSize.x, textureSize.y, GL_RGBA, GL_UNSIGNED_BYTE, textureBuffer); + texture.update(textureBuffer); + sprite.setTexture(texture, true); + context->setActive(false); + } } window.draw(sprite); |