| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- #include <obs-module.h>
- #include <util/platform.h>
- #include <memory>
- #include <algorithm>
- #include "mf-encoder-descriptor.hpp"
- using namespace MF;
- template<class T> class ComHeapPtr {
- protected:
- T *ptr;
- inline void Kill()
- {
- if (ptr)
- CoTaskMemFree(ptr);
- }
- inline void Replace(T *p)
- {
- if (ptr != p) {
- if (ptr) ptr->Kill();
- ptr = p;
- }
- }
- public:
- inline ComHeapPtr() : ptr(nullptr) {}
- inline ComHeapPtr(T *p) : ptr(p) {}
- inline ComHeapPtr(const ComHeapPtr<T> &c) = delete;
- inline ComHeapPtr(ComHeapPtr<T> &&c) = delete;
- inline ~ComHeapPtr() { Kill(); }
- inline void Clear()
- {
- if (ptr) {
- Kill();
- ptr = nullptr;
- }
- }
- inline ComPtr<T> &operator=(T *p)
- {
- Replace(p);
- return *this;
- }
- inline T *Detach()
- {
- T *out = ptr;
- ptr = nullptr;
- return out;
- }
- inline T **Assign() { Clear(); return &ptr; }
- inline void Set(T *p) { Kill(); ptr = p; }
- inline T *Get() const { return ptr; }
- inline T **operator&() { return Assign(); }
- inline operator T*() const { return ptr; }
- inline T *operator->() const { return ptr; }
- inline bool operator==(T *p) const { return ptr == p; }
- inline bool operator!=(T *p) const { return ptr != p; }
- inline bool operator!() const { return !ptr; }
- };
- struct EncoderEntry {
- const char *guid;
- const char *name;
- const char *id;
- EncoderType type;
- } guidNameMap[] = {
- {
- "{6CA50344-051A-4DED-9779-A43305165E35}",
- "MF.H264.EncoderSWMicrosoft",
- "mf_h264_software",
- EncoderType::H264_SOFTWARE
- },
- {
- "{ADC9BC80-0F41-46C6-AB75-D693D793597D}",
- "MF.H264.EncoderHWAMD",
- "mf_h264_vce",
- EncoderType::H264_VCE,
- },
- {
- "{4BE8D3C0-0515-4A37-AD55-E4BAE19AF471}",
- "MF.H264.EncoderHWIntel",
- "mf_h264_qsv",
- EncoderType::H264_QSV
- },
- {
- "{60F44560-5A20-4857-BFEF-D29773CB8040}",
- "MF.H264.EncoderHWNVIDIA",
- "mf_h264_nvenc",
- EncoderType::H264_NVENC
- }
- };
- static std::string MBSToString(wchar_t *mbs)
- {
- char *cstr;
- os_wcs_to_utf8_ptr(mbs, 0, &cstr);
- std::string str = cstr;
- bfree(cstr);
- return str;
- }
- static std::unique_ptr<EncoderDescriptor> CreateDescriptor(
- ComPtr<IMFActivate> activate)
- {
- UINT32 flags;
- if (FAILED(activate->GetUINT32(MF_TRANSFORM_FLAGS_Attribute, &flags)))
- return nullptr;
- bool isAsync = !(flags & MFT_ENUM_FLAG_SYNCMFT);
- isAsync |= !!(flags & MFT_ENUM_FLAG_ASYNCMFT);
- bool isHardware = !!(flags & MFT_ENUM_FLAG_HARDWARE);
- GUID guid = {0};
- if (FAILED(activate->GetGUID(MFT_TRANSFORM_CLSID_Attribute, &guid)))
- return nullptr;
- ComHeapPtr<WCHAR> guidW;
- StringFromIID(guid, &guidW);
- std::string guidString = MBSToString(guidW);
- auto pred = [guidString](const EncoderEntry &name) {
- return guidString == name.guid;
- };
- EncoderEntry *entry = std::find_if(std::begin(guidNameMap),
- std::end(guidNameMap), pred);
- std::unique_ptr<EncoderDescriptor> descriptor(new EncoderDescriptor(
- activate, entry->name, entry->id, guid, guidString,
- isAsync, isHardware, entry->type));
- return descriptor;
- }
- std::vector<std::shared_ptr<EncoderDescriptor>> EncoderDescriptor::Enumerate()
- {
- HRESULT hr;
- UINT32 count = 0;
- std::vector<std::shared_ptr<EncoderDescriptor>> descriptors;
- ComHeapPtr<IMFActivate *> ppActivate;
- MFT_REGISTER_TYPE_INFO info = { MFMediaType_Video, MFVideoFormat_H264 };
- UINT32 unFlags = 0;
- unFlags |= MFT_ENUM_FLAG_LOCALMFT;
- unFlags |= MFT_ENUM_FLAG_TRANSCODE_ONLY;
- unFlags |= MFT_ENUM_FLAG_SYNCMFT;
- unFlags |= MFT_ENUM_FLAG_ASYNCMFT;
- unFlags |= MFT_ENUM_FLAG_HARDWARE;
- unFlags |= MFT_ENUM_FLAG_SORTANDFILTER;
- hr = MFTEnumEx(MFT_CATEGORY_VIDEO_ENCODER,
- unFlags,
- NULL,
- &info,
- &ppActivate,
- &count);
- if (SUCCEEDED(hr) && count == 0) {
- return descriptors;
- }
- if (SUCCEEDED(hr)) {
- for (decltype(count) i = 0; i < count; i++) {
- auto p = std::move(CreateDescriptor(ppActivate[i]));
- if (p)
- descriptors.emplace_back(std::move(p));
- }
- }
- for (UINT32 i = 0; i < count; i++) {
- ppActivate[i]->Release();
- }
- return descriptors;
- }
|