mf-encoder-descriptor.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #include <obs-module.h>
  2. #include <util/platform.h>
  3. #include <memory>
  4. #include <algorithm>
  5. #include "mf-encoder-descriptor.hpp"
  6. using namespace MF;
  7. template<class T> class ComHeapPtr {
  8. protected:
  9. T *ptr;
  10. inline void Kill()
  11. {
  12. if (ptr)
  13. CoTaskMemFree(ptr);
  14. }
  15. inline void Replace(T *p)
  16. {
  17. if (ptr != p) {
  18. if (ptr) ptr->Kill();
  19. ptr = p;
  20. }
  21. }
  22. public:
  23. inline ComHeapPtr() : ptr(nullptr) {}
  24. inline ComHeapPtr(T *p) : ptr(p) {}
  25. inline ComHeapPtr(const ComHeapPtr<T> &c) = delete;
  26. inline ComHeapPtr(ComHeapPtr<T> &&c) = delete;
  27. inline ~ComHeapPtr() { Kill(); }
  28. inline void Clear()
  29. {
  30. if (ptr) {
  31. Kill();
  32. ptr = nullptr;
  33. }
  34. }
  35. inline ComPtr<T> &operator=(T *p)
  36. {
  37. Replace(p);
  38. return *this;
  39. }
  40. inline T *Detach()
  41. {
  42. T *out = ptr;
  43. ptr = nullptr;
  44. return out;
  45. }
  46. inline T **Assign() { Clear(); return &ptr; }
  47. inline void Set(T *p) { Kill(); ptr = p; }
  48. inline T *Get() const { return ptr; }
  49. inline T **operator&() { return Assign(); }
  50. inline operator T*() const { return ptr; }
  51. inline T *operator->() const { return ptr; }
  52. inline bool operator==(T *p) const { return ptr == p; }
  53. inline bool operator!=(T *p) const { return ptr != p; }
  54. inline bool operator!() const { return !ptr; }
  55. };
  56. struct EncoderEntry {
  57. const char *guid;
  58. const char *name;
  59. const char *id;
  60. EncoderType type;
  61. } guidNameMap[] = {
  62. {
  63. "{6CA50344-051A-4DED-9779-A43305165E35}",
  64. "MF.H264.EncoderSWMicrosoft",
  65. "mf_h264_software",
  66. EncoderType::H264_SOFTWARE
  67. },
  68. {
  69. "{ADC9BC80-0F41-46C6-AB75-D693D793597D}",
  70. "MF.H264.EncoderHWAMD",
  71. "mf_h264_vce",
  72. EncoderType::H264_VCE,
  73. },
  74. {
  75. "{4BE8D3C0-0515-4A37-AD55-E4BAE19AF471}",
  76. "MF.H264.EncoderHWIntel",
  77. "mf_h264_qsv",
  78. EncoderType::H264_QSV
  79. },
  80. {
  81. "{60F44560-5A20-4857-BFEF-D29773CB8040}",
  82. "MF.H264.EncoderHWNVIDIA",
  83. "mf_h264_nvenc",
  84. EncoderType::H264_NVENC
  85. }
  86. };
  87. static std::string MBSToString(wchar_t *mbs)
  88. {
  89. char *cstr;
  90. os_wcs_to_utf8_ptr(mbs, 0, &cstr);
  91. std::string str = cstr;
  92. bfree(cstr);
  93. return str;
  94. }
  95. static std::unique_ptr<EncoderDescriptor> CreateDescriptor(
  96. ComPtr<IMFActivate> activate)
  97. {
  98. UINT32 flags;
  99. if (FAILED(activate->GetUINT32(MF_TRANSFORM_FLAGS_Attribute, &flags)))
  100. return nullptr;
  101. bool isAsync = !(flags & MFT_ENUM_FLAG_SYNCMFT);
  102. isAsync |= !!(flags & MFT_ENUM_FLAG_ASYNCMFT);
  103. bool isHardware = !!(flags & MFT_ENUM_FLAG_HARDWARE);
  104. GUID guid = {0};
  105. if (FAILED(activate->GetGUID(MFT_TRANSFORM_CLSID_Attribute, &guid)))
  106. return nullptr;
  107. ComHeapPtr<WCHAR> guidW;
  108. StringFromIID(guid, &guidW);
  109. std::string guidString = MBSToString(guidW);
  110. auto pred = [guidString](const EncoderEntry &name) {
  111. return guidString == name.guid;
  112. };
  113. EncoderEntry *entry = std::find_if(std::begin(guidNameMap),
  114. std::end(guidNameMap), pred);
  115. std::unique_ptr<EncoderDescriptor> descriptor(new EncoderDescriptor(
  116. activate, entry->name, entry->id, guid, guidString,
  117. isAsync, isHardware, entry->type));
  118. return descriptor;
  119. }
  120. std::vector<std::shared_ptr<EncoderDescriptor>> EncoderDescriptor::Enumerate()
  121. {
  122. HRESULT hr;
  123. UINT32 count = 0;
  124. std::vector<std::shared_ptr<EncoderDescriptor>> descriptors;
  125. ComHeapPtr<IMFActivate *> ppActivate;
  126. MFT_REGISTER_TYPE_INFO info = { MFMediaType_Video, MFVideoFormat_H264 };
  127. UINT32 unFlags = 0;
  128. unFlags |= MFT_ENUM_FLAG_LOCALMFT;
  129. unFlags |= MFT_ENUM_FLAG_TRANSCODE_ONLY;
  130. unFlags |= MFT_ENUM_FLAG_SYNCMFT;
  131. unFlags |= MFT_ENUM_FLAG_ASYNCMFT;
  132. unFlags |= MFT_ENUM_FLAG_HARDWARE;
  133. unFlags |= MFT_ENUM_FLAG_SORTANDFILTER;
  134. hr = MFTEnumEx(MFT_CATEGORY_VIDEO_ENCODER,
  135. unFlags,
  136. NULL,
  137. &info,
  138. &ppActivate,
  139. &count);
  140. if (SUCCEEDED(hr) && count == 0) {
  141. return descriptors;
  142. }
  143. if (SUCCEEDED(hr)) {
  144. for (decltype(count) i = 0; i < count; i++) {
  145. auto p = std::move(CreateDescriptor(ppActivate[i]));
  146. if (p)
  147. descriptors.emplace_back(std::move(p));
  148. }
  149. }
  150. for (UINT32 i = 0; i < count; i++) {
  151. ppActivate[i]->Release();
  152. }
  153. return descriptors;
  154. }