Dynamically load libvlc

This commit is contained in:
hax0kartik 2020-04-13 22:41:57 +05:30
parent f4c4441308
commit 143ad394a9
3 changed files with 85 additions and 37 deletions

View File

@ -663,7 +663,7 @@ if(NOT ZM_NO_LIBVLC)
find_library(LIBVLC_LIBRARIES vlc)
if(LIBVLC_LIBRARIES)
set(HAVE_LIBVLC 1)
list(APPEND ZM_BIN_LIBS "${LIBVLC_LIBRARIES}")
#list(APPEND ZM_BIN_LIBS "${LIBVLC_LIBRARIES}")
find_path(LIBVLC_INCLUDE_DIR "vlc/vlc.h")
if(LIBVLC_INCLUDE_DIR)
include_directories("${LIBVLC_INCLUDE_DIR}")

View File

@ -24,6 +24,8 @@
#include "zm_packetqueue.h"
#if HAVE_LIBCURL
/* Func ptrs for libcurl functions */
static void *curl_lib = nullptr;
static CURLcode (*curl_global_init_f)(long) = nullptr;
@ -36,9 +38,6 @@ static CURLcode (*curl_easy_perform_f)(CURL*) = nullptr;
static CURLcode (*curl_easy_setopt_f)(CURL*, CURLoption, ...) = nullptr;
static void (*curl_easy_cleanup_f)(CURL*) = nullptr;
#if HAVE_LIBCURL
#define CURL_MAXRETRY 5
#define CURL_BUFFER_INITIAL_SIZE 65536
@ -47,6 +46,31 @@ const char* content_type_match = "Content-Type:";
size_t content_length_match_len;
size_t content_type_match_len;
void bind_libcurl_symbols() {
if(curl_lib)
return;
curl_lib = dlopen("libcurl.so", RTLD_LAZY | RTLD_GLOBAL);
if(!curl_lib)
curl_lib = dlopen("libcurl-gnutls.so.4", RTLD_LAZY | RTLD_GLOBAL);
if (!curl_lib) {
Error("Could not load libcurl: %s", dlerror());
return;
}
// Load up all required symbols here
*(void**) (&curl_global_init_f) = dlsym(curl_lib, "curl_global_init");
*(void**) (&curl_global_cleanup_f) = dlsym(curl_lib, "curl_global_cleanup");
*(void**) (&curl_easy_strerror_f) = dlsym(curl_lib, "curl_easy_strerror");
*(void**) (&curl_version_f) = dlsym(curl_lib, "curl_version");
*(void**) (&curl_easy_init_f) = dlsym(curl_lib, "curl_easy_init");
*(void**) (&curl_easy_getinfo_f) = dlsym(curl_lib, "curl_easy_getinfo");
*(void**) (&curl_easy_perform_f) = dlsym(curl_lib, "curl_easy_perform");
*(void**) (&curl_easy_setopt_f) = dlsym(curl_lib, "curl_easy_setopt");
*(void**) (&curl_easy_cleanup_f) = dlsym(curl_lib, "curl_easy_cleanup");
}
cURLCamera::cURLCamera( int p_id, const std::string &p_path, const std::string &p_user, const std::string &p_pass, unsigned int p_width, unsigned int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) :
Camera( p_id, CURL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ),
mPath( p_path ), mUser( p_user ), mPass ( p_pass ), bTerminate( false ), bReset( false ), mode ( MODE_UNSET )
@ -70,25 +94,7 @@ void cURLCamera::Initialise() {
databuffer.expand(CURL_BUFFER_INITIAL_SIZE);
curl_lib = dlopen("libcurl.so", RTLD_LAZY | RTLD_GLOBAL);
if(!curl_lib)
curl_lib = dlopen("libcurl-gnutls.so.4", RTLD_LAZY | RTLD_GLOBAL);
if (!curl_lib) {
Error("Could not load libcurl: %s", dlerror());
return;
}
// Load up all required symbols here
*(void**) (&curl_global_init_f) = dlsym(curl_lib, "curl_global_init");
*(void**) (&curl_global_cleanup_f) = dlsym(curl_lib, "curl_global_cleanup");
*(void**) (&curl_easy_strerror_f) = dlsym(curl_lib, "curl_easy_strerror");
*(void**) (&curl_version_f) = dlsym(curl_lib, "curl_version");
*(void**) (&curl_easy_init_f) = dlsym(curl_lib, "curl_easy_init");
*(void**) (&curl_easy_getinfo_f) = dlsym(curl_lib, "curl_easy_getinfo");
*(void**) (&curl_easy_perform_f) = dlsym(curl_lib, "curl_easy_perform");
*(void**) (&curl_easy_setopt_f) = dlsym(curl_lib, "curl_easy_setopt");
*(void**) (&curl_easy_cleanup_f) = dlsym(curl_lib, "curl_easy_cleanup");
bind_libcurl_symbols();
/* cURL initialization */
CURLcode cRet = (*curl_global_init_f)(CURL_GLOBAL_ALL);
if(cRet != CURLE_OK) {

View File

@ -17,12 +17,51 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <dlfcn.h>
#include "zm.h"
#include "zm_signal.h"
#include "zm_libvlc_camera.h"
#if HAVE_LIBVLC
static void *libvlc_lib = nullptr;
static void (*libvlc_media_player_release_f)(libvlc_media_player_t* ) = nullptr;
static void (*libvlc_media_release_f)(libvlc_media_t* ) = nullptr;
static void (*libvlc_release_f)(libvlc_instance_t* ) = nullptr;
static void (*libvlc_media_player_stop_f)(libvlc_media_player_t* ) = nullptr;
static libvlc_instance_t* (*libvlc_new_f)(int, const char* const *) = nullptr;
static void (*libvlc_log_set_f)(libvlc_instance_t*, libvlc_log_cb, void *) = nullptr;
static libvlc_media_t* (*libvlc_media_new_location_f)(libvlc_instance_t*, const char*) = nullptr;
static libvlc_media_player_t* (*libvlc_media_player_new_from_media_f)(libvlc_media_t*) = nullptr;
static void (*libvlc_video_set_format_f)(libvlc_media_player_t*, const char*, unsigned, unsigned, unsigned) = nullptr;
static void (*libvlc_video_set_callbacks_f)(libvlc_media_player_t*, libvlc_video_lock_cb, libvlc_video_unlock_cb, libvlc_video_display_cb, void*) = nullptr;
static int (*libvlc_media_player_play_f)(libvlc_media_player_t *) = nullptr;
static const char* (*libvlc_errmsg_f)(void) = nullptr;
static const char* (*libvlc_get_version_f)(void) = nullptr;
void bind_libvlc_symbols() {
if(libvlc_lib != nullptr) // Safe-check
return;
libvlc_lib = dlopen("libvlc.so", RTLD_LAZY | RTLD_GLOBAL);
if(!libvlc_lib){
Error("Error loading libvlc: %s", dlerror());
return;
}
*(void**) (&libvlc_media_player_release_f) = dlsym(libvlc_lib, "libvlc_media_player_release");
*(void**) (&libvlc_media_release_f) = dlsym(libvlc_lib, "libvlc_media_release");
*(void**) (&libvlc_release_f) = dlsym(libvlc_lib, "libvlc_release");
*(void**) (&libvlc_media_player_stop_f) = dlsym(libvlc_lib, "libvlc_media_player_stop");
*(void**) (&libvlc_new_f) = dlsym(libvlc_lib, "libvlc_new");
*(void**) (&libvlc_log_set_f) = dlsym(libvlc_lib, "libvlc_log_set");
*(void**) (&libvlc_media_new_location_f) = dlsym(libvlc_lib, "libvlc_media_new_location");
*(void**) (&libvlc_media_player_new_from_media_f) = dlsym(libvlc_lib, "libvlc_media_player_new_from_media");
*(void**) (&libvlc_video_set_format_f) = dlsym(libvlc_lib, "libvlc_video_set_format");
*(void**) (&libvlc_video_set_callbacks_f) = dlsym(libvlc_lib, "libvlc_video_set_callbacks");
*(void**) (&libvlc_media_player_play_f) = dlsym(libvlc_lib, "libvlc_media_player_play");
*(void**) (&libvlc_errmsg_f) = dlsym(libvlc_lib, "libvlc_errmsg");
*(void**) (&libvlc_get_version_f) = dlsym(libvlc_lib, "libvlc_get_version");
}
// Do all the buffer checking work here to avoid unnecessary locking
void* LibvlcLockBuffer(void* opaque, void** planes) {
LibvlcPrivateData* data = reinterpret_cast<LibvlcPrivateData*>(opaque);
@ -125,15 +164,15 @@ LibvlcCamera::~LibvlcCamera() {
Terminate();
}
if ( mLibvlcMediaPlayer != NULL ) {
libvlc_media_player_release(mLibvlcMediaPlayer);
(*libvlc_media_player_release_f)(mLibvlcMediaPlayer);
mLibvlcMediaPlayer = NULL;
}
if ( mLibvlcMedia != NULL ) {
libvlc_media_release(mLibvlcMedia);
(*libvlc_media_release_f)(mLibvlcMedia);
mLibvlcMedia = NULL;
}
if ( mLibvlcInstance != NULL ) {
libvlc_release(mLibvlcInstance);
(*libvlc_release_f)(mLibvlcInstance);
mLibvlcInstance = NULL;
}
if ( mOptArgV != NULL ) {
@ -142,14 +181,16 @@ LibvlcCamera::~LibvlcCamera() {
}
void LibvlcCamera::Initialise() {
bind_libvlc_symbols();
}
void LibvlcCamera::Terminate() {
libvlc_media_player_stop(mLibvlcMediaPlayer);
(*libvlc_media_player_stop_f)(mLibvlcMediaPlayer);
if ( mLibvlcData.buffer ) {
zm_freealigned(mLibvlcData.buffer);
mLibvlcData.buffer = NULL;
}
if ( mLibvlcData.prevBuffer ) {
zm_freealigned(mLibvlcData.prevBuffer);
mLibvlcData.prevBuffer = NULL;
@ -158,6 +199,7 @@ void LibvlcCamera::Terminate() {
int LibvlcCamera::PrimeCapture() {
Info("Priming capture from %s", mPath.c_str());
Info("Libvlc Version %s", (*libvlc_get_version_f)());
StringVector opVect = split(Options(), ",");
@ -181,28 +223,28 @@ int LibvlcCamera::PrimeCapture() {
}
}
mLibvlcInstance = libvlc_new(opVect.size(), (const char* const*)mOptArgV);
mLibvlcInstance = (*libvlc_new_f)(opVect.size(), (const char* const*)mOptArgV);
if ( mLibvlcInstance == NULL ) {
Error("Unable to create libvlc instance due to: %s", libvlc_errmsg());
Error("Unable to create libvlc instance due to: %s", (*libvlc_errmsg_f)());
return -1;
}
libvlc_log_set(mLibvlcInstance, LibvlcCamera::log_callback, NULL);
(*libvlc_log_set_f)(mLibvlcInstance, LibvlcCamera::log_callback, NULL);
mLibvlcMedia = libvlc_media_new_location(mLibvlcInstance, mPath.c_str());
mLibvlcMedia = (*libvlc_media_new_location_f)(mLibvlcInstance, mPath.c_str());
if ( mLibvlcMedia == NULL ) {
Error("Unable to open input %s due to: %s", mPath.c_str(), libvlc_errmsg());
Error("Unable to open input %s due to: %s", mPath.c_str(), (*libvlc_errmsg_f)());
return -1;
}
mLibvlcMediaPlayer = libvlc_media_player_new_from_media(mLibvlcMedia);
mLibvlcMediaPlayer = (*libvlc_media_player_new_from_media_f)(mLibvlcMedia);
if ( mLibvlcMediaPlayer == NULL ) {
Error("Unable to create player for %s due to: %s", mPath.c_str(), libvlc_errmsg());
Error("Unable to create player for %s due to: %s", mPath.c_str(), (*libvlc_errmsg_f)());
return -1;
}
libvlc_video_set_format(mLibvlcMediaPlayer, mTargetChroma.c_str(), width, height, width * mBpp);
libvlc_video_set_callbacks(mLibvlcMediaPlayer, &LibvlcLockBuffer, &LibvlcUnlockBuffer, NULL, &mLibvlcData);
(*libvlc_video_set_format_f)(mLibvlcMediaPlayer, mTargetChroma.c_str(), width, height, width * mBpp);
(*libvlc_video_set_callbacks_f)(mLibvlcMediaPlayer, &LibvlcLockBuffer, &LibvlcUnlockBuffer, NULL, &mLibvlcData);
mLibvlcData.bufferSize = width * height * mBpp;
// Libvlc wants 32 byte alignment for images (should in theory do this for all image lines)
@ -211,7 +253,7 @@ int LibvlcCamera::PrimeCapture() {
mLibvlcData.newImage.setValueImmediate(false);
libvlc_media_player_play(mLibvlcMediaPlayer);
(*libvlc_media_player_play_f)(mLibvlcMediaPlayer);
return 0;
}