Dynamically load libvlc
This commit is contained in:
parent
f4c4441308
commit
143ad394a9
|
@ -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}")
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue