Графическое оборудование Intel H264 MFT Вызов ProcessInput завершается неудачно после подачи нескольких входных выборок, то же самое отлично работает с аппаратным обеспечением MFT от Nvidia


9

Я собираю десктоп с помощью DesktopDuplication API и преобразую сэмплы из RGBA в NV12 в графическом процессоре и передаю их на аппаратное обеспечение MediaFoundation H264 MFT. Это прекрасно работает с графикой Nvidia, а также с программными кодировщиками, но дает сбой, когда доступно только графическое оборудование Intel 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 encoder & Асинхронный MFT не отправляет событие MFTransformHaveOutput (аппаратное обеспечение Intel 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;
}

Реализация асинхронного обратного вызова:

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/ форум / БЕЗОПАСНОСТЬ / EN-US / fe051dd5-b522-4e4b-9cbb-2c06a5450e40 / imfsinkwriter-заслуги валидация-неудавшаяся для-MFT-Intel-быстрая синхронизация видео-h264-кодер-MFT? форум = mediafoundationdevelopment

Обновление: я попытался смоделировать только источник входного сигнала (путем программного создания образца анимирующего прямоугольника NV12), оставив все остальное нетронутым. На этот раз кодировщик intel ни на что не жалуется, у меня даже есть выходные образцы. За исключением того факта, что выходное видео кодера Intel искажено, тогда как кодер Nvidia работает отлично.

Кроме того, я все еще получаю ошибку ProcessInput для моего исходного источника NV12 с кодировщиком Intel. У меня нет проблем с Nvidia MFT и программными кодировщиками.

Вывод аппаратного обеспечения Intel MFT: (Пожалуйста, посмотрите на вывод кодера Nvidia) введите описание изображения здесь

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

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

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


Соответствующий код не показан. Вполне вероятно, что что-то пойдет не так с получением «нужной информации» и ее предоставлением ProcessInput.
Роман Р.

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

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

Кстати, код с той ссылки на форуме 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 GPU и 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

Не могли бы вы сначала проверить возможности видеопроцессора вашего графического процессора. Вы видите ту же разницу, что и я?

Это первое, что нам нужно знать, и, похоже, ваша программа не проверяет это, исходя из того, что я видел в вашем проекте github.


Вы правы. GetVideoProcessorOutputFormats для графики Intel возвращает только варианты RGB и YUY2.
Рам

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

У вас есть шейдер или компьютерный шейдер.
mofo77

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

Большой! Спасибо за обмен, это действительно полезно.
Рам

1

Как упоминалось в посте, ошибка MEError («Unspecified error») была возвращена генератором событий Transform сразу после подачи первой выборки ввода на аппаратном обеспечении 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.