hardware_acceleration.cpp 5.6 KB

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