libnvcuvid.so.init.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*
  2. * Copyright 2018-2020 Yury Gribov
  3. *
  4. * The MIT License (MIT)
  5. *
  6. * Use of this source code is governed by MIT license that can be
  7. * found in the LICENSE.txt file.
  8. */
  9. #include <dlfcn.h>
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <assert.h>
  13. // Sanity check for ARM to avoid puzzling runtime crashes
  14. #ifdef __arm__
  15. # if defined __thumb__ && ! defined __THUMB_INTERWORK__
  16. # error "ARM trampolines need -mthumb-interwork to work in Thumb mode"
  17. # endif
  18. #endif
  19. #ifdef __cplusplus
  20. extern "C" {
  21. #endif
  22. #define CHECK(cond, fmt, ...) do { \
  23. if(!(cond)) { \
  24. fprintf(stderr, "implib-gen: libnvcuvid.so: " fmt "\n", ##__VA_ARGS__); \
  25. assert(0 && "Assertion in generated code"); \
  26. exit(1); \
  27. } \
  28. } while(0)
  29. #define CALL_USER_CALLBACK 0
  30. #define NO_DLOPEN False
  31. #define LAZY_LOAD 1
  32. static void *lib_handle;
  33. static int is_lib_loading;
  34. static void *load_library() {
  35. if(lib_handle)
  36. return lib_handle;
  37. is_lib_loading = 1;
  38. // TODO: dlopen and users callback must be protected w/ critical section (to avoid dlopening lib twice)
  39. #if NO_DLOPEN
  40. CHECK(0, "internal error"); // We shouldn't get here
  41. #elif CALL_USER_CALLBACK
  42. extern void *(const char *lib_name);
  43. lib_handle = ("libnvcuvid.so");
  44. CHECK(lib_handle, "callback '' failed to load library");
  45. #else
  46. lib_handle = dlopen("libnvcuvid.so", RTLD_LAZY | RTLD_GLOBAL);
  47. CHECK(lib_handle, "failed to load library: %s", dlerror());
  48. #endif
  49. is_lib_loading = 0;
  50. return lib_handle;
  51. }
  52. #if ! NO_DLOPEN && ! LAZY_LOAD
  53. static void __attribute__((constructor)) load_lib() {
  54. load_library();
  55. }
  56. #endif
  57. static void __attribute__((destructor)) unload_lib() {
  58. if(lib_handle)
  59. dlclose(lib_handle);
  60. }
  61. // TODO: convert to single 0-separated string
  62. static const char *const sym_names[] = {
  63. "__std_1U4S4U_X02",
  64. "__std_2U4S4U_X08",
  65. "__std_4U4S4U_X04",
  66. "cuvidConvertYUVToRGB",
  67. "cuvidConvertYUVToRGBArray",
  68. "cuvidCreateDecoder",
  69. "cuvidCreateVideoParser",
  70. "cuvidCreateVideoSource",
  71. "cuvidCreateVideoSourceW",
  72. "cuvidCtxLock",
  73. "cuvidCtxLockCreate",
  74. "cuvidCtxLockDestroy",
  75. "cuvidCtxUnlock",
  76. "cuvidDecodePicture",
  77. "cuvidDestroyDecoder",
  78. "cuvidDestroyVideoParser",
  79. "cuvidDestroyVideoSource",
  80. "cuvidGetDecodeStatus",
  81. "cuvidGetDecoderCaps",
  82. "cuvidGetSourceAudioFormat",
  83. "cuvidGetSourceVideoFormat",
  84. "cuvidGetVideoSourceState",
  85. "cuvidMapVideoFrame",
  86. "cuvidMapVideoFrame64",
  87. "cuvidParseVideoData",
  88. "cuvidPrivateOp",
  89. "cuvidReconfigureDecoder",
  90. "cuvidSetVideoSourceState",
  91. "cuvidUnmapVideoFrame",
  92. "cuvidUnmapVideoFrame64",
  93. 0
  94. };
  95. extern void *_libnvcuvid_so_tramp_table[];
  96. // Can be sped up by manually parsing library symtab...
  97. void _libnvcuvid_so_tramp_resolve(int i) {
  98. assert((unsigned)i + 1 < sizeof(sym_names) / sizeof(sym_names[0]));
  99. CHECK(!is_lib_loading, "library function '%s' called during library load", sym_names[i]);
  100. void *h = 0;
  101. #if NO_DLOPEN
  102. // FIXME: instead of RTLD_NEXT we should search for loaded lib_handle
  103. // as in https://github.com/jethrogb/ssltrace/blob/bf17c150a7/ssltrace.cpp#L74-L112
  104. h = RTLD_NEXT;
  105. #elif LAZY_LOAD
  106. h = load_library();
  107. #else
  108. h = lib_handle;
  109. CHECK(h, "failed to resolve symbol '%s', library failed to load", sym_names[i]);
  110. #endif
  111. // Dlsym is thread-safe so don't need to protect it.
  112. _libnvcuvid_so_tramp_table[i] = dlsym(h, sym_names[i]);
  113. CHECK(_libnvcuvid_so_tramp_table[i], "failed to resolve symbol '%s'", sym_names[i]);
  114. }
  115. // Helper for user to resolve all symbols
  116. void _libnvcuvid_so_tramp_resolve_all(void) {
  117. size_t i;
  118. for(i = 0; i + 1 < sizeof(sym_names) / sizeof(sym_names[0]); ++i)
  119. _libnvcuvid_so_tramp_resolve(i);
  120. }
  121. #ifdef __cplusplus
  122. } // extern "C"
  123. #endif