Графічне обладнання Intel H264 MFT ProcessInput виходить з ладу після подачі декількох вхідних зразків, це добре працює з апаратним обладнанням Nvidia MFT


9

Я захоплюю робочий стіл за допомогою API DesktopDuplication і конвертую зразки з RGBA до NV12 в GPU і подаю те ж саме на апаратне забезпечення H264 MFT MediaFoundation. Це чудово працює з графікою Nvidia, а також із програмними кодерами, але виходить з ладу, коли доступний лише апаратний графічний апарат MFT MFT. Код добре працює на тій же графічній машині Intel, якщо я повернувся до Software MFT. Я також переконався, що кодування фактично робиться апаратно на графічних машинах Nvidia.

У графіці Intel, MFT повертає MEError ( "Невизначена помилка" ), що відбувається лише після подачі першого зразка, а наступні виклики до ProcessInput (коли генератор подій запускає METransformNeedInput) повертається "Оголошення наразі не приймає подальшого введення" . Рідко коли MFT споживає ще кілька зразків, перш ніж повернути ці помилки. Така поведінка є заплутаною, я подаю зразок лише тоді, коли генератор подій запускає METransformNeedInput асинхронно через IMFAsyncCallback, а також перевіряю, чи спрацьовує METransformHaveOutput, як тільки зразок подається. Це насправді бентежить, коли та ж асинхронна логіка працює добре з апаратними кодерами програмного забезпечення MFT та Microsoft Nvidia.

Подібне невирішене питання також існує на самому форумі Intel. Мій код схожий на той, що згадується в потоці Intel, за винятком того, що я також встановлюю диспетчер пристроїв d3d на кодер, як нижче.

І, є три інших переповнення стека нитки звітність подібний питання без якого - небудь рішення даного ( MFTransform encoder-> ProcessInput повертає E_FAIL & Як створити IMFSample від D11 текстури для Intel MFT кодувальника і асинхронної MFT не надсилає MFTransformHaveOutput Event (Intel Hardware MJPEG Decoder MFT) ). Я перепробував всі можливі варіанти, не покращуючи це.

Код перетворювача кольорів береться з зразків Intel media sdk. Я також завантажив сюди свій повний код .

Спосіб встановлення d3d-менеджера:

void SetD3dManager() {

    HRESULT hr = S_OK;

    if (!deviceManager) {

        // Create device manager
        hr = MFCreateDXGIDeviceManager(&resetToken, &deviceManager);
    }

    if (SUCCEEDED(hr)) 
    {
        if (!pD3dDevice) {

            pD3dDevice = GetDeviceDirect3D(0);
        }
    }

    if (pD3dDevice) {

        // NOTE: Getting ready for multi-threaded operation
        const CComQIPtr<ID3D10Multithread> pMultithread = pD3dDevice;
        pMultithread->SetMultithreadProtected(TRUE);

        hr = deviceManager->ResetDevice(pD3dDevice, resetToken);
        CHECK_HR(_pTransform->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, reinterpret_cast<ULONG_PTR>(deviceManager.p)), "Failed to set device manager.");
    }
    else {
        cout << "Failed to get d3d device";
    }
}

Getd3ddevice:

CComPtr<ID3D11Device> GetDeviceDirect3D(UINT idxVideoAdapter)
{
    // Create DXGI factory:
    CComPtr<IDXGIFactory1> dxgiFactory;
    DXGI_ADAPTER_DESC1 dxgiAdapterDesc;

    // Direct3D feature level codes and names:

    struct KeyValPair { int code; const char* name; };

    const KeyValPair d3dFLevelNames[] =
    {
        KeyValPair{ D3D_FEATURE_LEVEL_9_1, "Direct3D 9.1" },
        KeyValPair{ D3D_FEATURE_LEVEL_9_2, "Direct3D 9.2" },
        KeyValPair{ D3D_FEATURE_LEVEL_9_3, "Direct3D 9.3" },
        KeyValPair{ D3D_FEATURE_LEVEL_10_0, "Direct3D 10.0" },
        KeyValPair{ D3D_FEATURE_LEVEL_10_1, "Direct3D 10.1" },
        KeyValPair{ D3D_FEATURE_LEVEL_11_0, "Direct3D 11.0" },
        KeyValPair{ D3D_FEATURE_LEVEL_11_1, "Direct3D 11.1" },
    };

    // Feature levels for Direct3D support
    const D3D_FEATURE_LEVEL d3dFeatureLevels[] =
    {
        D3D_FEATURE_LEVEL_11_1,
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_9_3,
        D3D_FEATURE_LEVEL_9_2,
        D3D_FEATURE_LEVEL_9_1,
    };

    constexpr auto nFeatLevels = static_cast<UINT> ((sizeof d3dFeatureLevels) / sizeof(D3D_FEATURE_LEVEL));

    CComPtr<IDXGIAdapter1> dxgiAdapter;
    D3D_FEATURE_LEVEL featLevelCodeSuccess;
    CComPtr<ID3D11Device> d3dDx11Device;

    std::wstring_convert<std::codecvt_utf8<wchar_t>> transcoder;

    HRESULT hr = CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory));
    CHECK_HR(hr, "Failed to create DXGI factory");

    // Get a video adapter:
    dxgiFactory->EnumAdapters1(idxVideoAdapter, &dxgiAdapter);

    // Get video adapter description:
    dxgiAdapter->GetDesc1(&dxgiAdapterDesc);

    CHECK_HR(hr, "Failed to retrieve DXGI video adapter description");

    std::cout << "Selected DXGI video adapter is \'"
        << transcoder.to_bytes(dxgiAdapterDesc.Description) << '\'' << std::endl;

    // Create Direct3D device:
    hr = D3D11CreateDevice(
        dxgiAdapter,
        D3D_DRIVER_TYPE_UNKNOWN,
        nullptr,
        (0 * D3D11_CREATE_DEVICE_SINGLETHREADED) | D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
        d3dFeatureLevels,
        nFeatLevels,
        D3D11_SDK_VERSION,
        &d3dDx11Device,
        &featLevelCodeSuccess,
        nullptr
    );

    // Might have failed for lack of Direct3D 11.1 runtime:
    if (hr == E_INVALIDARG)
    {
        // Try again without Direct3D 11.1:
        hr = D3D11CreateDevice(
            dxgiAdapter,
            D3D_DRIVER_TYPE_UNKNOWN,
            nullptr,
            (0 * D3D11_CREATE_DEVICE_SINGLETHREADED) | D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
            d3dFeatureLevels + 1,
            nFeatLevels - 1,
            D3D11_SDK_VERSION,
            &d3dDx11Device,
            &featLevelCodeSuccess,
            nullptr
        );
    }

    // Get name of Direct3D feature level that succeeded upon device creation:
    std::cout << "Hardware device supports " << std::find_if(
        d3dFLevelNames,
        d3dFLevelNames + nFeatLevels,
        [featLevelCodeSuccess](const KeyValPair& entry)
        {
            return entry.code == featLevelCodeSuccess;
        }
    )->name << std::endl;

done:

    return d3dDx11Device;
}

Реалізація зворотного дзвінка Async:

struct EncoderCallbacks : IMFAsyncCallback
{
    EncoderCallbacks(IMFTransform* encoder)
    {
        TickEvent = CreateEvent(0, FALSE, FALSE, 0);
        _pEncoder = encoder;
    }

    ~EncoderCallbacks()
    {
        eventGen = nullptr;
        CloseHandle(TickEvent);
    }

    bool Initialize() {

        _pEncoder->QueryInterface(IID_PPV_ARGS(&eventGen));

        if (eventGen) {

            eventGen->BeginGetEvent(this, 0);
            return true;
        }

        return false;
    }

    // dummy IUnknown impl
    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override { return E_NOTIMPL; }
    virtual ULONG STDMETHODCALLTYPE AddRef(void) override { return 1; }
    virtual ULONG STDMETHODCALLTYPE Release(void) override { return 1; }

    virtual HRESULT STDMETHODCALLTYPE GetParameters(DWORD* pdwFlags, DWORD* pdwQueue) override
    {
        // we return immediately and don't do anything except signaling another thread
        *pdwFlags = MFASYNC_SIGNAL_CALLBACK;
        *pdwQueue = MFASYNC_CALLBACK_QUEUE_IO;
        return S_OK;
    }

    virtual HRESULT STDMETHODCALLTYPE Invoke(IMFAsyncResult* pAsyncResult) override
    {
        IMFMediaEvent* event = 0;
        eventGen->EndGetEvent(pAsyncResult, &event);
        if (event)
        {
            MediaEventType type;
            event->GetType(&type);
            switch (type)
            {
            case METransformNeedInput: InterlockedIncrement(&NeedsInput); break;
            case METransformHaveOutput: InterlockedIncrement(&HasOutput); break;
            }
            event->Release();
            SetEvent(TickEvent);
        }

        eventGen->BeginGetEvent(this, 0);
        return S_OK;
    }

    CComQIPtr<IMFMediaEventGenerator> eventGen = nullptr;
    HANDLE TickEvent;
    IMFTransform* _pEncoder = nullptr;

    unsigned int NeedsInput = 0;
    unsigned int HasOutput = 0;
};

Створення зразкового методу:

bool GenerateSampleAsync() {

    DWORD processOutputStatus = 0;
    HRESULT mftProcessOutput = S_OK;
    bool frameSent = false;

    // Create sample
    CComPtr<IMFSample> currentVideoSample = nullptr;

    MFT_OUTPUT_STREAM_INFO StreamInfo;

    // wait for any callback to come in
    WaitForSingleObject(_pEventCallback->TickEvent, INFINITE);

    while (_pEventCallback->NeedsInput) {

        if (!currentVideoSample) {

            (pDesktopDuplication)->releaseBuffer();
            (pDesktopDuplication)->cleanUpCurrentFrameObjects();

            bool bTimeout = false;

            if (pDesktopDuplication->GetCurrentFrameAsVideoSample((void**)& currentVideoSample, waitTime, bTimeout, deviceRect, deviceRect.Width(), deviceRect.Height())) {

                prevVideoSample = currentVideoSample;
            }
            // Feed the previous sample to the encoder in case of no update in display
            else {
                currentVideoSample = prevVideoSample;
            }
        }

        if (currentVideoSample)
        {
            InterlockedDecrement(&_pEventCallback->NeedsInput);
            _frameCount++;

            CHECK_HR(currentVideoSample->SetSampleTime(mTimeStamp), "Error setting the video sample time.");
            CHECK_HR(currentVideoSample->SetSampleDuration(VIDEO_FRAME_DURATION), "Error getting video sample duration.");

            CHECK_HR(_pTransform->ProcessInput(inputStreamID, currentVideoSample, 0), "The resampler H264 ProcessInput call failed.");

            mTimeStamp += VIDEO_FRAME_DURATION;
        }
    }

    while (_pEventCallback->HasOutput) {

        CComPtr<IMFSample> mftOutSample = nullptr;
        CComPtr<IMFMediaBuffer> pOutMediaBuffer = nullptr;

        InterlockedDecrement(&_pEventCallback->HasOutput);

        CHECK_HR(_pTransform->GetOutputStreamInfo(outputStreamID, &StreamInfo), "Failed to get output stream info from H264 MFT.");

        CHECK_HR(MFCreateSample(&mftOutSample), "Failed to create MF sample.");
        CHECK_HR(MFCreateMemoryBuffer(StreamInfo.cbSize, &pOutMediaBuffer), "Failed to create memory buffer.");
        CHECK_HR(mftOutSample->AddBuffer(pOutMediaBuffer), "Failed to add sample to buffer.");

        MFT_OUTPUT_DATA_BUFFER _outputDataBuffer;
        memset(&_outputDataBuffer, 0, sizeof _outputDataBuffer);
        _outputDataBuffer.dwStreamID = outputStreamID;
        _outputDataBuffer.dwStatus = 0;
        _outputDataBuffer.pEvents = nullptr;
        _outputDataBuffer.pSample = mftOutSample;

        mftProcessOutput = _pTransform->ProcessOutput(0, 1, &_outputDataBuffer, &processOutputStatus);

        if (mftProcessOutput != MF_E_TRANSFORM_NEED_MORE_INPUT)
        {
            if (_outputDataBuffer.pSample) {

                CComPtr<IMFMediaBuffer> buf = NULL;
                DWORD bufLength;
                CHECK_HR(_outputDataBuffer.pSample->ConvertToContiguousBuffer(&buf), "ConvertToContiguousBuffer failed.");

                if (buf) {

                    CHECK_HR(buf->GetCurrentLength(&bufLength), "Get buffer length failed.");
                    BYTE* rawBuffer = NULL;

                    fFrameSize = bufLength;
                    fDurationInMicroseconds = 0;
                    gettimeofday(&fPresentationTime, NULL);

                    buf->Lock(&rawBuffer, NULL, NULL);
                    memmove(fTo, rawBuffer, fFrameSize > fMaxSize ? fMaxSize : fFrameSize);

                    bytesTransfered += bufLength;

                    FramedSource::afterGetting(this);

                    buf->Unlock();

                    frameSent = true;
                }
            }

            if (_outputDataBuffer.pEvents)
                _outputDataBuffer.pEvents->Release();
        }
        else if (MF_E_TRANSFORM_STREAM_CHANGE == mftProcessOutput) {

            // some encoders want to renegotiate the output format. 
            if (_outputDataBuffer.dwStatus & MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE)
            {
                CComPtr<IMFMediaType> pNewOutputMediaType = nullptr;
                HRESULT res = _pTransform->GetOutputAvailableType(outputStreamID, 1, &pNewOutputMediaType);

                res = _pTransform->SetOutputType(0, pNewOutputMediaType, 0);//setting the type again
                CHECK_HR(res, "Failed to set output type during stream change");
            }
        }
        else {
            HandleFailure();
        }
    }

    return frameSent;
}

Створіть зразок відео та перетворення кольорів:

bool GetCurrentFrameAsVideoSample(void **videoSample, int waitTime, bool &isTimeout, CRect &deviceRect, int surfaceWidth, int surfaceHeight)
{

FRAME_DATA currentFrameData;

m_LastErrorCode = m_DuplicationManager.GetFrame(&currentFrameData, waitTime, &isTimeout);

if (!isTimeout && SUCCEEDED(m_LastErrorCode)) {

    m_CurrentFrameTexture = currentFrameData.Frame;

    if (!pDstTexture) {

        D3D11_TEXTURE2D_DESC desc;
        ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));

        desc.Format = DXGI_FORMAT_NV12;
        desc.Width = surfaceWidth;
        desc.Height = surfaceHeight;
        desc.MipLevels = 1;
        desc.ArraySize = 1;
        desc.SampleDesc.Count = 1;
        desc.CPUAccessFlags = 0;
        desc.Usage = D3D11_USAGE_DEFAULT;
        desc.BindFlags = D3D11_BIND_RENDER_TARGET;

        m_LastErrorCode = m_Id3d11Device->CreateTexture2D(&desc, NULL, &pDstTexture);
    }

    if (m_CurrentFrameTexture && pDstTexture) {

        // Copy diff area texels to new temp texture
        //m_Id3d11DeviceContext->CopySubresourceRegion(pNewTexture, D3D11CalcSubresource(0, 0, 1), 0, 0, 0, m_CurrentFrameTexture, 0, NULL);

        HRESULT hr = pColorConv->Convert(m_CurrentFrameTexture, pDstTexture);

        if (SUCCEEDED(hr)) { 

            CComPtr<IMFMediaBuffer> pMediaBuffer = nullptr;

            MFCreateDXGISurfaceBuffer(__uuidof(ID3D11Texture2D), pDstTexture, 0, FALSE, (IMFMediaBuffer**)&pMediaBuffer);

            if (pMediaBuffer) {

                CComPtr<IMF2DBuffer> p2DBuffer = NULL;
                DWORD length = 0;
                (((IMFMediaBuffer*)pMediaBuffer))->QueryInterface(__uuidof(IMF2DBuffer), reinterpret_cast<void**>(&p2DBuffer));
                p2DBuffer->GetContiguousLength(&length);
                (((IMFMediaBuffer*)pMediaBuffer))->SetCurrentLength(length);

                //MFCreateVideoSampleFromSurface(NULL, (IMFSample**)videoSample);
                MFCreateSample((IMFSample * *)videoSample);

                if (videoSample) {

                    (*((IMFSample **)videoSample))->AddBuffer((((IMFMediaBuffer*)pMediaBuffer)));
                }

                return true;
            }
        }
    }
}

return false;
}

Графічний драйвер Intel в машині вже оновлений.

введіть тут опис зображення введіть тут опис зображення введіть тут опис зображення

Лише подія TransformNeedInput постійно спрацьовує, але кодер скаржиться, що більше не може прийняти введення. Подія TransformHaveOutput ніколи не була запущена.

введіть тут опис зображення

Про подібні проблеми повідомлялося на форумах intel & msdn: 1) https://software.intel.com/en-us/forums/intel-media-sdk/topic/607189 2) https://social.msdn.microsoft.com/ Форуми / SECURITY / en-US / fe051dd5-b522-4e4b-9cbb-2c06a5450e40 / imfsinkwriter-merit-validation-fail-for-mft-intel-quick-sync-video-h264-encoder-mft? Forum = mediafoundationdevelopment

Оновлення: Я намагався знущатися над лише джерелом введення (програмуючи створення анімаційного прямокутника зразка NV12), залишаючи все інше недоторканим. Цього разу кодер Intel не скаржиться ні на що, у мене навіть є вихідні зразки. За винятком того, що вихідне відео кодера Intel викривлено, тоді як кодер Nvidia працює чудово.

Крім того, я все ще отримую помилку ProcessInput для мого оригінального джерела NV12 з кодером Intel. У мене немає проблем з Nvidia MFT та програмними кодерами.

Вихід обладнання MFT MFT: (Погляньте на вихід кодера Nvidia) введіть тут опис зображення

Вихід апаратного забезпечення MFT: введіть тут опис зображення

Статистика використання графіки Nvidia: введіть тут опис зображення

Статистика використання графіки Intel (я не розумію, чому двигун GPU відображається як декодування відео): введіть тут опис зображення


Немає відповідного коду. Цілком ймовірно, що щось піде не так, як саме навколо отримання "потрібного вкладу" та надання його ProcessInput.
Роман Р.

@RomanR. якщо це так, це може також не вдатися до програмного забезпечення та NFTia Hardware MFT, чи не так? Я не показав жодного коду, пов’язаного із перерахуванням конфігурацій MFT та конфігурацій вводу та виводу, тому що це буде зайвим, непотрібним і занадто довгим для потоку, як я вже згадував, що я дотримувався саме того самого коду, що вказаний на Intel forum ( software.intel.com / en-us / форуми / intel-media-sdk / тема / 681571 ). Я спробую оновити цей потік необхідними кодовими блоками.
Рам

Ні, це не. Обладнання MFT від AMD, Intel та NVIDIA реалізує однаково, але в той же час дещо іншу поведінку. Усі три в основному працюють як асинхронні MFT, тому ваше запитання є очевидним свідченням того, що ви робите щось не так. Без коду це лише здогадки, що саме. Програмний кодер Microsoft синхронізує MFT AFAIR, тому цілком ймовірно, що це частина спілкування з async MFT - це те, де щось не в порядку.
Роман Р.

BTW код із цього посилання на форум Intel працює на мене і створює відео.
Роман Р.

@RomanR. Я оновив потік із моєю реалізацією IMFAsyncCallback, створення зразків та перетворення кольорів, ProcessInput та ProcessOutput. Кольоровий перетворювач просто взято звідси ( github.com/NVIDIA/video-sdk-samples/blob/master/… ).
Рам

Відповіді:


2

Я подивився на ваш код.

Відповідно до вашого допису, я підозрюю, що у відеопроцесора Intel є проблема.

Моя ОС - це Win7, тому я вирішу перевірити поведінку відеопроцесора за допомогою D3D9Device на моїй картці Nvidia, а потім на Intel HD Graphics 4000.

Я припускаю, що можливості відеопроцесора поводяться так само, як і для D3D9Device, як і для D3D11Device. Звичайно, потрібно буде перевірити.

Тому я зробив цю програму для перевірки: https://github.com/mofo7777/DirectXVideoScreen (див. Підпроект D3D9VideoProcessor)

Здається, ви не перевіряєте достатньо речей щодо можливостей відеопроцесора.

З IDXVAHD_Device :: GetVideoProcessorDeviceCaps, ось що я перевіряю:

DXVAHD_VPDEVCAPS.MaxInputStreams> 0

DXVAHD_VPDEVCAPS.VideoProcessorCount> 0

DXVAHD_VPDEVCAPS.OutputFormatCount> 0

DXVAHD_VPDEVCAPS.InputFormatCount> 0

DXVAHD_VPDEVCAPS.InputPool == D3DPOOL_DEFAULT

Я також перевіряю формат вводу та виводу, підтримуваний IDXVAHD_Device :: GetVideoProcessorOutputFormats та IDXVAHD_Device :: GetVideoProcessorInputFormats.

Тут я знайшов різницю між процесором Nvidia та Intel GPU.

NVIDIA: 4 вихідний формат

  • D3DFMT_A8R8G8B8
  • D3DFMT_X8R8G8B8
  • D3DFMT_YUY2
  • D3DFMT_NV12

INTEL: 3 вихідний формат

  • D3DFMT_A8R8G8B8
  • D3DFMT_X8R8G8B8
  • D3DFMT_YUY2

У Intel HD Graphics 4000 відсутня підтримка вихідного формату NV12.

Також, щоб програма працювала правильно, мені потрібно встановити стан потоку перед використанням VideoProcessBltHD:

  • DXVAHD_STREAM_STATE_D3DFORMAT
  • DXVAHD_STREAM_STATE_FRAME_FORMAT
  • DXVAHD_STREAM_STATE_INPUT_COLOR_SPACE
  • DXVAHD_STREAM_STATE_SOURCE_RECT
  • DXVAHD_STREAM_STATE_DESTINATION_RECT

Для D3D11:

ID3D11VideoProcessorEnumerator :: GetVideoProcessorCaps == IDXVAHD_Device :: GetVideoProcessorDeviceCaps

(D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_OUTPUT) ID3D11VideoProcessorEnumerator :: CheckVideoProcessorFormat == IDXVAHD_Device :: GetVideoProcessorOutputFormats

(D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_INPUT) ID3D11VideoProcessorEnumerator :: CheckVideoProcessorFormat == IDXVAHD_Device :: GetVideoProcessorInputFormats

ID3D11VideoContext :: (...) == IDXVAHD_VideoProcessor :: SetVideoProcessStreamState

Чи можете ви спочатку перевірити можливості відеопроцесора свого GPU. Ви бачите таку ж різницю, як і я?

Це перше, що нам потрібно знати, і, здається, ваша програма цього не перевіряє, що я бачив у вашому проекті github.


Ти правий. GetVideoProcessorOutputFormats на графіку Intel повернув лише варіанти RGB та YUY2.
Рам

Мені легко вдається перетворити текстуру RGBA в YUY2 на процесорах Intel. Але суть, здається, графіка Intel підтримує лише формат введення NV12. Тепер перетворювач кольорів та відеокодер не сумісні. Мені все ще цікаво, чому Intel вирішила зробити так. Чи є якийсь інший спосіб зробити перетворення RGB в NV12 ефективно ?. Я вже спробував програмні підходи, які не забезпечують належної продуктивності.
Рам

У вас є шейдер або обчислити шейдер.
mofo77

1
Я працюю над шейдерним підходом. Перевірте github.com/mofo7777/DirectXVideoScreen на оновлення.
mofo77

Чудово! Дякуємо, що поділилися, це дуже корисно.
Рам

1

Як згадується у публікації, помилка MEError ("Невизначена помилка") повертається генератором Transform's Event відразу після подачі першого зразка вводу на апаратне забезпечення Intel, а подальше виклики щойно повертаються "Transform Need more input", але вихід не вироблявся . Цей же код добре працював на машинах Nvidia. Експериментувавши і дослідивши багато, я зрозумів, що створюю занадто багато примірників D3d11Device. У моєму випадку я створив 2 - 3 пристрої для захоплення, перетворення кольорів та апаратного кодера відповідно. Тоді як я міг би просто використати один екземпляр D3dDevice. Створення декількох екземплярів D3d11Device може працювати на машинах високого класу. Це ніде не зафіксовано. Мені не вдалося знайти навіть підказки щодо причин помилки "MEError". Ніде не згадується.

Повторне використання екземпляра D3D11Device вирішило проблему. Опублікувати це рішення, як це може бути корисно для людей, які стикаються з тією ж проблемою, що і моя.


Я не бачу у вашій публікації, де згадується помилка E_UNEXPECTED ...
mofo77

@ mofo77, Вибачте, це було MEError = 1 ("Невизначена помилка"), як згадується у публікації. Я якось втратив розум. Виправив мою відповідь. Дякуємо, що вказали.
Рам
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.