From 8ddfe0707aad9fd10188fd9a06a03f348d68d21c Mon Sep 17 00:00:00 2001 From: dragonflylee Date: Mon, 13 Nov 2023 15:32:23 +0800 Subject: [PATCH] add mpv demo --- CMakeLists.txt | 7 ++- Makefile | 4 +- Makefile.mingw | 2 +- src/main.cpp | 144 ++++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 134 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d0bf80..19b87e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,10 +25,15 @@ set_target_properties(xplayer PROPERTIES CXX_STANDARD 17) target_include_directories(xplayer PRIVATE ${CMAKE_SOURCE_DIR}) target_compile_definitions(xplayer PRIVATE ${RENDER_DRIVER}) +find_package(PkgConfig REQUIRED) +pkg_search_module(MPV REQUIRED mpv) +target_include_directories(xplayer PRIVATE ${MPV_INCLUDE_DIRS}) + if (NINTENDO_SWITCH) target_link_libraries(xplayer PRIVATE sdl2 glapi drm_nouveau nx m + ${MPV_LINK_LIBRARIES} ) nx_generate_nacp(xplayer.nacp NAME "xplayer demo" AUTHOR dragonflylee VERSION 1.0) nx_create_nro(xplayer ICON ${CMAKE_SOURCE_DIR}/icon.jpg NACP xplayer.nacp) @@ -37,6 +42,6 @@ else () if (MINGW) set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++") endif () - target_link_libraries(xplayer PRIVATE ${SDL2_LIBRARIES}) + target_link_libraries(xplayer PRIVATE ${SDL2_LIBRARIES} ${MPV_LINK_LIBRARIES}) endif () diff --git a/Makefile b/Makefile index 2c97443..0e613d1 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- TARGET := xPlayer BUILD := build -SRCS := src imgui +SRCS := src DATA := data #ROMFS := romfs @@ -25,7 +25,7 @@ CFLAGS += $(INCLUDE) -D__SWITCH__ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -DIMGUI_IMPL_OPENGL_LOADER_CUSTOM ASFLAGS := -g $(ARCH) LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) -LIBS := `$(PREFIX)pkg-config sdl2 --libs` +LIBS := `$(PREFIX)pkg-config sdl2 mpv --libs` -lnx #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/Makefile.mingw b/Makefile.mingw index 3ef2c8e..d04e238 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -6,7 +6,7 @@ OBJS = $(SRCS:.cpp=.o) INCLUDES := -I$(CURDIR) CFLAGS := -g -Wall $(INCLUDES) CXXFLAGS := $(CFLAGS) -std=c++17 -LDFLAGS := `pkg-config sdl2 --libs` +LDFLAGS := `pkg-config sdl2 mpv --libs` all: $(TARGET) diff --git a/src/main.cpp b/src/main.cpp index 1abec3d..b4bba3c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,6 @@ -#include -#include - #include +#include +#include #ifdef __SWITCH__ #include @@ -10,32 +9,30 @@ extern "C" void userAppInit() { socketInitializeDefault(); nxlinkStdio(); appletSetWirelessPriorityMode(AppletWirelessPriorityMode_OptimizedForWlan); - plInitialize(PlServiceType_User); + sslInitialize(0x3); + csrngInitialize(); } extern "C" void userAppExit() { - plExit(); + csrngExit(); + sslExit(); socketExit(); } #endif -// some switch buttons -#define JOY_A 0 -#define JOY_B 1 -#define JOY_X 2 -#define JOY_Y 3 -#define JOY_PLUS 10 +#define JOY_A 0 +#define JOY_PLUS 10 #define JOY_MINUS 11 -#define JOY_LEFT 12 -#define JOY_UP 13 -#define JOY_RIGHT 14 -#define JOY_DOWN 15 static void die(const char* msg) { - fprintf(stderr, "%s\n", msg); + SDL_Log("%s\n", msg); exit(1); } +static inline void check_error(int status) { + if (status < 0) SDL_Log("mpv error: %s\n", mpv_error_string(status)); +} + // Main code int main(int argc, char* argv[]) { if (argc < 2) die("pass a single media file as argument"); @@ -45,36 +42,145 @@ int main(int argc, char* argv[]) { SDL_JoystickEventState(SDL_ENABLE); SDL_JoystickOpen(0); + mpv_render_context* mpv_context = nullptr; + mpv_handle* mpv = mpv_create(); + mpv_set_option_string(mpv, "subs-fallback", "yes"); + mpv_set_option_string(mpv, "video-timing-offset", "0"); // 60fps + mpv_set_option_string(mpv, "ytdl", "no"); + mpv_set_option_string(mpv, "hwdec", "auto-copy"); + mpv_set_option_string(mpv, "vo", "libmpv"); + if (mpv_initialize(mpv) < 0) die("init mpv failed"); + SDL_Window* window = SDL_CreateWindow(argv[1], 0, 0, 1280, 720, 0); if (!window) die("failed to create SDL window"); SDL_GLContext context = SDL_GL_CreateContext(window); SDL_GL_MakeCurrent(window, context); + mpv_opengl_init_params gl_init_params{ + [](void* fn_ctx, const char* name) { return (void*)SDL_GL_GetProcAddress(name); }, nullptr}; + mpv_render_param params[] = { + {MPV_RENDER_PARAM_API_TYPE, const_cast(MPV_RENDER_API_TYPE_OPENGL)}, + {MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_init_params}, + {MPV_RENDER_PARAM_INVALID, nullptr}, + }; + + if (mpv_render_context_create(&mpv_context, mpv, params) < 0) die("init mpv context failed"); + + static uint32_t SDL_MPV_RENDER = SDL_RegisterEvents(1); + static uint32_t SDL_MPV_EVENT = SDL_RegisterEvents(1); + + mpv_set_wakeup_callback( + mpv, + [](void* obj) { + SDL_Event event = {.type = SDL_MPV_EVENT}; + SDL_PushEvent(&event); + }, + nullptr); + + mpv_render_context_set_update_callback( + mpv_context, + [](void* obj) { + SDL_Event event = {.type = SDL_MPV_RENDER}; + SDL_PushEvent(&event); + }, + nullptr); + + const char* args[] = {"loadfile", argv[1], nullptr}; + if (mpv_command_async(mpv, 0, args) < 0) die("load file failed"); + + int fbw = 0, fbh = 0; SDL_Event event; while (SDL_WaitEvent(&event)) { + int redraw = 0; switch (event.type) { case SDL_QUIT: goto done; + case SDL_WINDOWEVENT: + if (event.window.event == SDL_WINDOWEVENT_EXPOSED) redraw = 1; + break; case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_ESCAPE: goto done; + case SDLK_RETURN: + mpv_command_string(mpv, "script-binding stats/display-stats-toggle"); + break; + case SDLK_SPACE: + mpv_command_string(mpv, "cycle pause"); + break; } break; case SDL_JOYBUTTONDOWN: switch (event.jbutton.button) { case JOY_PLUS: goto done; + case JOY_MINUS: + mpv_command_string(mpv, "script-binding stats/display-stats-toggle"); + break; + case JOY_A: + mpv_command_string(mpv, "cycle pause"); + break; + default: + SDL_Log("Joystick %d button %d down\n", event.jbutton.which, event.jbutton.button); } - SDL_Log("Joystick %d button %d down\n", event.jbutton.which, event.jbutton.button); break; - default:; + default: + if (event.type == SDL_MPV_RENDER) { + uint64_t flags = mpv_render_context_update(mpv_context); + if (flags & MPV_RENDER_UPDATE_FRAME) redraw = 1; + } else if (event.type == SDL_MPV_EVENT) { + while (true) { + mpv_event* mp_event = mpv_wait_event(mpv, 0); + if (mp_event->event_id == MPV_EVENT_NONE) { + break; + } else if (mp_event->event_id == MPV_EVENT_START_FILE) { + SDL_Log("MPV => START FILE\n"); + } else if (mp_event->event_id == MPV_EVENT_FILE_LOADED) { + SDL_Log("MPV => FILE LOADED\n"); + } else if (mp_event->event_id == MPV_EVENT_PLAYBACK_RESTART) { + SDL_Log("MPV => PLAYBACK RESTART\n"); + } else if (mp_event->event_id == MPV_EVENT_COMMAND_REPLY) { + if (mp_event->error) { + SDL_Log("MPV => COMMAND ERROR: %s\n", mpv_error_string(mp_event->error)); + break; + } + } else if (mp_event->event_id == MPV_EVENT_END_FILE) { + auto node = (mpv_event_end_file*)mp_event->data; + if (node->reason == MPV_END_FILE_REASON_ERROR) { + SDL_Log("MPV => FILE ERROR: %s\n", mpv_error_string(node->error)); + } else if (node->reason == MPV_END_FILE_REASON_EOF) { + SDL_Log("MPV => END_OF_FILE\n"); + } else { + SDL_Log("MPV => STOP\n"); + } + goto done; + } else if (mp_event->event_id == MPV_EVENT_PROPERTY_CHANGE) { + /// https://mpv.io/manual/stable/#property-list + mpv_event_property* prop = (mpv_event_property*)mp_event->data; + SDL_Log("MPV => PROPERTY `%s` type %d\n", prop->name, int(prop->format)); + } + } + } } - SDL_GL_SwapWindow(window); + if (redraw) { + SDL_GL_GetDrawableSize(window, &fbw, &fbh); + mpv_opengl_fbo mpv_fbo{0, fbw, fbh}; + int flip_y{1}; + mpv_render_param mpv_params[3] = { + {MPV_RENDER_PARAM_OPENGL_FBO, &mpv_fbo}, + {MPV_RENDER_PARAM_FLIP_Y, &flip_y}, + {MPV_RENDER_PARAM_INVALID, nullptr}, + }; + mpv_render_context_render(mpv_context, mpv_params); + SDL_GL_SwapWindow(window); + } } done: + mpv_render_context_free(mpv_context); + mpv_terminate_destroy(mpv); + SDL_GL_DeleteContext(context); SDL_DestroyWindow(window); SDL_Quit();