Adds the ability to add video playlists via libvlc instead of via the media source. This is mostly just being added as a secondary option to the media source to reduce maintenance costs and save time. Currently libff cannot pause/unpause/seek, and isn't programmed to handle playlists yet. If VLC is installed on the computer (with the same architecture) it will allow video playback via libVLC. In the future, users should be able to optionally download VLC libraries via the installer as well if they don't want to necessarily install VLC to get the plugin working. This plugin performs runtime linking instead of compile-time linking; compiling VLC is not required, only its headers are required. To compile, clone the VLC repository and set the VLCPath cmake variable to point to the VLC repository directory.
202 lines
5.8 KiB
C
202 lines
5.8 KiB
C
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#include <util/platform.h>
|
|
#include "vlc-video-plugin.h"
|
|
|
|
OBS_DECLARE_MODULE()
|
|
OBS_MODULE_USE_DEFAULT_LOCALE("vlc-video", "en-US")
|
|
|
|
/* libvlc core */
|
|
LIBVLC_NEW libvlc_new_;
|
|
LIBVLC_RELEASE libvlc_release_;
|
|
LIBVLC_CLOCK libvlc_clock_;
|
|
LIBVLC_EVENT_ATTACH libvlc_event_attach_;
|
|
|
|
/* libvlc media */
|
|
LIBVLC_MEDIA_NEW_PATH libvlc_media_new_path_;
|
|
LIBVLC_MEDIA_RELEASE libvlc_media_release_;
|
|
LIBVLC_MEDIA_RELEASE libvlc_media_retain_;
|
|
|
|
/* libvlc media player */
|
|
LIBVLC_MEDIA_PLAYER_NEW libvlc_media_player_new_;
|
|
LIBVLC_MEDIA_PLAYER_NEW_FROM_MEDIA libvlc_media_player_new_from_media_;
|
|
LIBVLC_MEDIA_PLAYER_RELEASE libvlc_media_player_release_;
|
|
LIBVLC_VIDEO_SET_CALLBACKS libvlc_video_set_callbacks_;
|
|
LIBVLC_VIDEO_SET_FORMAT_CALLBACKS libvlc_video_set_format_callbacks_;
|
|
LIBVLC_AUDIO_SET_CALLBACKS libvlc_audio_set_callbacks_;
|
|
LIBVLC_AUDIO_SET_FORMAT_CALLBACKS libvlc_audio_set_format_callbacks_;
|
|
LIBVLC_MEDIA_PLAYER_PLAY libvlc_media_player_play_;
|
|
LIBVLC_MEDIA_PLAYER_STOP libvlc_media_player_stop_;
|
|
LIBVLC_MEDIA_PLAYER_GET_TIME libvlc_media_player_get_time_;
|
|
LIBVLC_VIDEO_GET_SIZE libvlc_video_get_size_;
|
|
LIBVLC_MEDIA_PLAYER_EVENT_MANAGER libvlc_media_player_event_manager_;
|
|
|
|
/* libvlc media list */
|
|
LIBVLC_MEDIA_LIST_NEW libvlc_media_list_new_;
|
|
LIBVLC_MEDIA_LIST_RELEASE libvlc_media_list_release_;
|
|
LIBVLC_MEDIA_LIST_ADD_MEDIA libvlc_media_list_add_media_;
|
|
LIBVLC_MEDIA_LIST_LOCK libvlc_media_list_lock_;
|
|
LIBVLC_MEDIA_LIST_UNLOCK libvlc_media_list_unlock_;
|
|
LIBVLC_MEDIA_LIST_EVENT_MANAGER libvlc_media_list_event_manager_;
|
|
|
|
/* libvlc media list player */
|
|
LIBVLC_MEDIA_LIST_PLAYER_NEW libvlc_media_list_player_new_;
|
|
LIBVLC_MEDIA_LIST_PLAYER_RELEASE libvlc_media_list_player_release_;
|
|
LIBVLC_MEDIA_LIST_PLAYER_PLAY libvlc_media_list_player_play_;
|
|
LIBVLC_MEDIA_LIST_PLAYER_PAUSE libvlc_media_list_player_pause_;
|
|
LIBVLC_MEDIA_LIST_PLAYER_STOP libvlc_media_list_player_stop_;
|
|
LIBVLC_MEDIA_LIST_PLAYER_SET_MEDIA_PLAYER libvlc_media_list_player_set_media_player_;
|
|
LIBVLC_MEDIA_LIST_PLAYER_SET_MEDIA_LIST libvlc_media_list_player_set_media_list_;
|
|
LIBVLC_MEDIA_LIST_PLAYER_EVENT_MANAGER libvlc_media_list_player_event_manager_;
|
|
LIBVLC_MEDIA_LIST_PLAYER_SET_PLAYBACK_MODE libvlc_media_list_player_set_playback_mode_;
|
|
|
|
void *libvlc_module = NULL;
|
|
libvlc_instance_t *libvlc = NULL;
|
|
uint64_t time_start = 0;
|
|
|
|
static bool load_vlc_funcs(void)
|
|
{
|
|
#define LOAD_VLC_FUNC(func) \
|
|
do { \
|
|
func ## _ = os_dlsym(libvlc_module, #func); \
|
|
if (!func ## _) { \
|
|
blog(LOG_WARNING, "Could not func VLC function %s, " \
|
|
"VLC loading failed", #func); \
|
|
return false; \
|
|
} \
|
|
} while (false)
|
|
|
|
/* libvlc core */
|
|
LOAD_VLC_FUNC(libvlc_new);
|
|
LOAD_VLC_FUNC(libvlc_release);
|
|
LOAD_VLC_FUNC(libvlc_clock);
|
|
LOAD_VLC_FUNC(libvlc_event_attach);
|
|
|
|
/* libvlc media */
|
|
LOAD_VLC_FUNC(libvlc_media_new_path);
|
|
LOAD_VLC_FUNC(libvlc_media_release);
|
|
LOAD_VLC_FUNC(libvlc_media_retain);
|
|
|
|
/* libvlc media player */
|
|
LOAD_VLC_FUNC(libvlc_media_player_new);
|
|
LOAD_VLC_FUNC(libvlc_media_player_new_from_media);
|
|
LOAD_VLC_FUNC(libvlc_media_player_release);
|
|
LOAD_VLC_FUNC(libvlc_video_set_callbacks);
|
|
LOAD_VLC_FUNC(libvlc_video_set_format_callbacks);
|
|
LOAD_VLC_FUNC(libvlc_audio_set_callbacks);
|
|
LOAD_VLC_FUNC(libvlc_audio_set_format_callbacks);
|
|
LOAD_VLC_FUNC(libvlc_media_player_play);
|
|
LOAD_VLC_FUNC(libvlc_media_player_stop);
|
|
LOAD_VLC_FUNC(libvlc_media_player_get_time);
|
|
LOAD_VLC_FUNC(libvlc_video_get_size);
|
|
LOAD_VLC_FUNC(libvlc_media_player_event_manager);
|
|
|
|
/* libvlc media list */
|
|
LOAD_VLC_FUNC(libvlc_media_list_new);
|
|
LOAD_VLC_FUNC(libvlc_media_list_release);
|
|
LOAD_VLC_FUNC(libvlc_media_list_add_media);
|
|
LOAD_VLC_FUNC(libvlc_media_list_lock);
|
|
LOAD_VLC_FUNC(libvlc_media_list_unlock);
|
|
LOAD_VLC_FUNC(libvlc_media_list_event_manager);
|
|
|
|
/* libvlc media list player */
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_new);
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_release);
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_play);
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_pause);
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_stop);
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_set_media_player);
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_set_media_list);
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_event_manager);
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_set_playback_mode);
|
|
return true;
|
|
}
|
|
|
|
static bool load_libvlc_module(void)
|
|
{
|
|
#ifdef _WIN32
|
|
char *path_utf8 = NULL;
|
|
wchar_t path[1024];
|
|
LSTATUS status;
|
|
DWORD size;
|
|
HKEY key;
|
|
|
|
memset(path, 0, 1024 * sizeof(wchar_t));
|
|
|
|
status = RegOpenKeyW(HKEY_LOCAL_MACHINE,
|
|
L"SOFTWARE\\VideoLAN\\VLC",
|
|
&key);
|
|
if (status != ERROR_SUCCESS)
|
|
return false;
|
|
|
|
size = 1024;
|
|
status = RegQueryValueExW(key, L"InstallDir", NULL, NULL,
|
|
(LPBYTE)path, &size);
|
|
if (status == ERROR_SUCCESS) {
|
|
wcscat(path, L"\\libvlc.dll");
|
|
os_wcs_to_utf8_ptr(path, 0, &path_utf8);
|
|
libvlc_module = os_dlopen(path_utf8);
|
|
bfree(path_utf8);
|
|
}
|
|
|
|
RegCloseKey(key);
|
|
#else
|
|
|
|
#ifdef __APPLE__
|
|
#define LIBVLC_DIR "/Applications/VLC.app/Contents/MacOS/"
|
|
#define LIBVLC_FILE LIBVLC_DIR "lib/libvlc.5.dylib"
|
|
setenv("VLC_PLUGIN_PATH", LIBVLC_DIR "plugins", false);
|
|
#else
|
|
#define LIBVLC_FILE "libvlc.5.so"
|
|
#endif
|
|
libvlc_module = os_dlopen(LIBVLC_FILE);
|
|
|
|
#endif
|
|
|
|
return libvlc_module != NULL;
|
|
}
|
|
|
|
extern struct obs_source_info vlc_source_info;
|
|
|
|
bool load_libvlc(void)
|
|
{
|
|
if (libvlc)
|
|
return true;
|
|
|
|
libvlc = libvlc_new_(0, 0);
|
|
if (!libvlc) {
|
|
blog(LOG_INFO, "Couldn't create libvlc instance");
|
|
return false;
|
|
}
|
|
|
|
time_start = (uint64_t)libvlc_clock_() * 1000ULL;
|
|
return true;
|
|
}
|
|
|
|
bool obs_module_load(void)
|
|
{
|
|
if (!load_libvlc_module()) {
|
|
blog(LOG_INFO, "Couldn't find VLC installation, VLC video "
|
|
"source disabled");
|
|
return true;
|
|
}
|
|
|
|
if (!load_vlc_funcs())
|
|
return true;
|
|
|
|
blog(LOG_INFO, "VLC found, VLC video source enabled");
|
|
|
|
obs_register_source(&vlc_source_info);
|
|
return true;
|
|
}
|
|
|
|
void obs_module_unload(void)
|
|
{
|
|
if (libvlc)
|
|
libvlc_release_(libvlc);
|
|
if (libvlc_module)
|
|
os_dlclose(libvlc_module);
|
|
}
|