#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#define HAS_DLOPEN_CALLBACK 0
#define HAS_DLSYM_CALLBACK 0
#define NO_DLOPEN 0
#define LAZY_LOAD 1
#define THREAD_SAFE 1
#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#if THREAD_SAFE
#include <pthread.h>
#endif
#ifdef __arm__
# if defined __thumb__ && ! defined __THUMB_INTERWORK__
# error "ARM trampolines need -mthumb-interwork to work in Thumb mode"
# endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define CHECK(cond, fmt, ...) do { \
if(!(cond)) { \
fprintf(stderr, "implib-gen: libnvcuvid.so.1: " fmt "\n", ##__VA_ARGS__); \
assert(0 && "Assertion in generated code"); \
abort(); \
} \
} while(0)
static void *lib_handle;
static int dlopened;
#if ! NO_DLOPEN
#if THREAD_SAFE
static pthread_mutex_t mtx;
static int rec_count;
static void init_lock(void) {
pthread_mutexattr_t attr;
CHECK(0 == pthread_mutexattr_init(&attr), "failed to init mutex");
CHECK(0 == pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE), "failed to init mutex");
CHECK(0 == pthread_mutex_init(&mtx, &attr), "failed to init mutex");
}
static int lock(void) {
static pthread_once_t once = PTHREAD_ONCE_INIT;
CHECK(0 == pthread_once(&once, init_lock), "failed to init lock");
CHECK(0 == pthread_mutex_lock(&mtx), "failed to lock mutex");
return 0 == __sync_fetch_and_add(&rec_count, 1);
}
static void unlock(void) {
__sync_fetch_and_add(&rec_count, -1);
CHECK(0 == pthread_mutex_unlock(&mtx), "failed to unlock mutex");
}
#else
static int lock(void) {
return 1;
}
static void unlock(void) {}
#endif
static int load_library(void) {
int publish = lock();
if (lib_handle) {
unlock();
return publish;
}
#if HAS_DLOPEN_CALLBACK
extern void *(const char *lib_name);
lib_handle = ("libnvcuvid.so.1");
CHECK(lib_handle, "failed to load library 'libnvcuvid.so.1' via callback ''");
#else
lib_handle = dlopen("libnvcuvid.so.1", RTLD_LAZY | RTLD_GLOBAL);
CHECK(lib_handle, "failed to load library 'libnvcuvid.so.1' via dlopen: %s", dlerror());
#endif
if (__sync_val_compare_and_swap(&dlopened, 0, 1)) {
dlclose(lib_handle);
}
unlock();
return publish;
}
static void __attribute__((destructor(101))) unload_lib(void) {
if (dlopened) {
dlclose(lib_handle);
lib_handle = 0;
dlopened = 0;
}
}
#endif
#if ! NO_DLOPEN && ! LAZY_LOAD
static void __attribute__((constructor(101))) load_lib(void) {
load_library();
}
#endif
static const char *const sym_names[] = {
"NvToolCreateInterface",
"NvToolDestroyInterface",
"NvToolGetApiFunctionCount",
"NvToolGetApiID",
"NvToolGetApiNames",
"NvToolGetInterface",
"NvToolSetApiID",
"NvToolSetInterface",
"__std_1U4S4U_X02",
"__std_2U4S4U_X08",
"__std_4U4S4U_X04",
"cuvidConvertYUVToRGB",
"cuvidConvertYUVToRGBArray",
"cuvidCreateDecoder",
"cuvidCreateVideoParser",
"cuvidCreateVideoSource",
"cuvidCreateVideoSourceW",
"cuvidCtxLock",
"cuvidCtxLockCreate",
"cuvidCtxLockDestroy",
"cuvidCtxUnlock",
"cuvidDecodePicture",
"cuvidDestroyDecoder",
"cuvidDestroyVideoParser",
"cuvidDestroyVideoSource",
"cuvidGetDecodeStatus",
"cuvidGetDecoderCaps",
"cuvidGetSourceAudioFormat",
"cuvidGetSourceVideoFormat",
"cuvidGetVideoSourceState",
"cuvidMapVideoFrame",
"cuvidMapVideoFrame64",
"cuvidParseVideoData",
"cuvidPrivateOp",
"cuvidReconfigureDecoder",
"cuvidSetVideoSourceState",
"cuvidUnmapVideoFrame",
"cuvidUnmapVideoFrame64",
0
};
#define SYM_COUNT (sizeof(sym_names)/sizeof(sym_names[0]) - 1)
extern void *_libnvcuvid_so_tramp_table[];
void *_libnvcuvid_so_tramp_resolve(size_t i) {
assert(i < SYM_COUNT);
int publish = 1;
void *h = 0;
#if NO_DLOPEN
if (lib_handle) {
h = lib_handle;
} else {
# ifndef IMPLIB_EXPORT_SHIMS
h = RTLD_DEFAULT;
# else
h = RTLD_NEXT;
# endif
}
#else
publish = load_library();
h = lib_handle;
CHECK(h, "failed to resolve symbol '%s', library failed to load", sym_names[i]);
#endif
void *addr;
#if HAS_DLSYM_CALLBACK
extern void *(void *handle, const char *sym_name);
addr = (h, sym_names[i]);
CHECK(addr, "failed to resolve symbol '%s' via callback ", sym_names[i]);
#else
addr = dlsym(h, sym_names[i]);
CHECK(addr, "failed to resolve symbol '%s' via dlsym: %s", sym_names[i], dlerror());
#endif
if (publish) {
(void)__sync_val_compare_and_swap(&_libnvcuvid_so_tramp_table[i], 0, addr);
}
return addr;
}
void _libnvcuvid_so_tramp_resolve_all(void) {
size_t i;
for(i = 0; i < SYM_COUNT; ++i)
_libnvcuvid_so_tramp_resolve(i);
}
void _libnvcuvid_so_tramp_set_handle(void *handle) {
lib_handle = handle;
dlopened = 0;
}
void _libnvcuvid_so_tramp_reset(void) {
memset(_libnvcuvid_so_tramp_table, 0, SYM_COUNT * sizeof(_libnvcuvid_so_tramp_table[0]));
lib_handle = 0;
dlopened = 0;
}
#ifdef __cplusplus
} #endif