hardware_acceleration.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #include "hardware_acceleration.h"
  2. #include <map>
  3. #include <algorithm>
  4. #include "headers_ffmpeg.h"
  5. #include "d3d_helper.h"
  6. #include "log_helper.h"
  7. #include "utils_string.h"
  8. #include "error_define.h"
  9. namespace am {
  10. static const std::map<_HARDWARE_TYPE, const char*> encoder_map = {
  11. { HARDWARE_TYPE_NVENC , "Nvidia.NVENC" },
  12. { HARDWARE_TYPE_QSV , "Intel.QSV" },
  13. { HARDWARE_TYPE_AMF , "AMD.AMF" },
  14. { HARDWARE_TYPE_VAAPI , "FFmpeg.Vaapi"}
  15. };
  16. static const std::list<std::string> nvenc_blacklist = {
  17. "720M", "730M", "740M", "745M", "820M", "830M",
  18. "840M", "845M", "920M", "930M", "940M", "945M",
  19. "1030", "MX110", "MX130", "MX150", "MX230", "MX250",
  20. "M520", "M500", "P500", "K620M"
  21. };
  22. static bool get_encoder_name(HARDWARE_TYPE type, char name[ENCODER_NAME_LEN]);
  23. static bool is_nvenc_blacklist(std::string desc);
  24. static bool is_nvenc_canload();
  25. static bool is_nvenc_support();
  26. static bool is_qsv_support();
  27. static bool is_amf_support();
  28. static bool is_vaapi_support();
  29. bool get_encoder_name(HARDWARE_TYPE type, char name[ENCODER_NAME_LEN]) {
  30. if (encoder_map.find(type) == encoder_map.end()) return false;
  31. strcpy_s(name, ENCODER_NAME_LEN, utils_string::ascii_utf8(encoder_map.at(type)).c_str());
  32. return true;
  33. }
  34. bool is_nvenc_blacklist(std::string desc) {
  35. for (auto itr = nvenc_blacklist.begin(); itr != nvenc_blacklist.end(); itr++) {
  36. if (desc.find((*itr).c_str()) != std::string::npos)
  37. return true;
  38. }
  39. return false;
  40. }
  41. bool is_nvenc_canload() {
  42. std::string module_name;
  43. if (sizeof(void *) == 8) {
  44. module_name = "nvEncodeAPI64.dll";
  45. }
  46. else {
  47. module_name = "nvEncodeAPI.dll";
  48. }
  49. HMODULE hnvenc = GetModuleHandleA(module_name.c_str());
  50. if (!hnvenc)
  51. hnvenc = LoadLibraryA(module_name.c_str());
  52. bool is_canload = !!hnvenc;
  53. if (hnvenc) FreeModule(hnvenc);
  54. return is_canload;
  55. }
  56. bool is_nvenc_support() {
  57. bool is_support = false;
  58. #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
  59. av_register_all();
  60. #endif
  61. do {
  62. if (avcodec_find_encoder_by_name("nvenc_h264") == nullptr &&
  63. avcodec_find_encoder_by_name("h264_nvenc") == nullptr)
  64. break;
  65. #if defined(_WIN32)
  66. int error = AE_NO;
  67. auto adapters = d3d_helper::get_adapters(&error);
  68. if (error != AE_NO || adapters.size() == 0)
  69. break;
  70. bool has_device = false;
  71. for (std::list<IDXGIAdapter *>::iterator itr = adapters.begin(); itr != adapters.end(); itr++) {
  72. IDXGIOutput *adapter_output = nullptr;
  73. DXGI_ADAPTER_DESC adapter_desc = { 0 };
  74. DXGI_OUTPUT_DESC adapter_output_desc = { 0 };
  75. HRESULT hr = (*itr)->GetDesc(&adapter_desc);
  76. std::string strdesc = utils_string::unicode_ascii(adapter_desc.Description);
  77. std::transform(strdesc.begin(), strdesc.end(), strdesc.begin(), ::toupper);
  78. if (SUCCEEDED(hr) && (strdesc.find("NVIDIA") != std::string::npos) && !is_nvenc_blacklist(strdesc)) {
  79. has_device = true;
  80. break;
  81. }
  82. }
  83. if(!has_device) break;
  84. if (!is_nvenc_canload()) break;
  85. #else
  86. /*
  87. if (!os_dlopen("libnvidia-encode.so.1"))
  88. break;
  89. */
  90. #endif
  91. is_support = true;
  92. } while (0);
  93. return is_support;
  94. }
  95. bool is_qsv_support() {
  96. bool is_support = false;
  97. return is_support;
  98. }
  99. bool is_amf_support() {
  100. bool is_support = false;
  101. return is_support;
  102. }
  103. bool is_vaapi_support() {
  104. bool is_support = false;
  105. return is_support;
  106. }
  107. std::vector<std::string> hardware_acceleration::get_video_hardware_devices() {
  108. std::vector<std::string> devices;
  109. enum AVHWDeviceType type = AV_HWDEVICE_TYPE_NONE;
  110. while ((type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE) {
  111. devices.push_back(av_hwdevice_get_type_name(type));
  112. al_debug("%s",av_hwdevice_get_type_name(type));
  113. }
  114. AVCodec *nvenc = avcodec_find_encoder_by_name("nvenc_h264");
  115. if(nvenc == nullptr)
  116. nvenc = avcodec_find_encoder_by_name("h264_nvenc");
  117. if (nvenc)
  118. al_debug("nvenc support");
  119. AVCodec *vaapi = avcodec_find_encoder_by_name("h264_qsv");
  120. if (vaapi)
  121. al_debug("qsv support");
  122. return devices;
  123. }
  124. std::list<HARDWARE_ENCODER> hardware_acceleration::get_supported_video_encoders() {
  125. std::list<HARDWARE_ENCODER> encoders;
  126. HARDWARE_ENCODER encoder;
  127. encoder.type = HARDWARE_TYPE_NVENC;
  128. if (is_nvenc_support() && get_encoder_name(encoder.type, encoder.name)) {
  129. encoders.push_back(encoder);
  130. }
  131. encoder.type = HARDWARE_TYPE_QSV;
  132. if (is_qsv_support() && get_encoder_name(encoder.type, encoder.name)) {
  133. encoders.push_back(encoder);
  134. }
  135. encoder.type = HARDWARE_TYPE_AMF;
  136. if (is_amf_support() && get_encoder_name(encoder.type, encoder.name)) {
  137. encoders.push_back(encoder);
  138. }
  139. encoder.type = HARDWARE_TYPE_VAAPI;
  140. if (is_vaapi_support() && get_encoder_name(encoder.type, encoder.name)) {
  141. encoders.push_back(encoder);
  142. }
  143. return encoders;
  144. }
  145. }