diff --git a/CMakeLists.txt b/CMakeLists.txt index 91dd4d9c3..a38697800 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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}") diff --git a/src/zm_curl_camera.cpp b/src/zm_curl_camera.cpp index 1d403a9e3..93b356c5e 100644 --- a/src/zm_curl_camera.cpp +++ b/src/zm_curl_camera.cpp @@ -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) { diff --git a/src/zm_libvlc_camera.cpp b/src/zm_libvlc_camera.cpp index 1998d1854..1bb3bd8cb 100644 --- a/src/zm_libvlc_camera.cpp +++ b/src/zm_libvlc_camera.cpp @@ -17,12 +17,51 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include #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(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; }