Sprzęt graficzny Intel H264 MFT Wywołanie ProcessInput kończy się niepowodzeniem po podaniu kilku próbek wejściowych, to samo działa dobrze ze sprzętem Nvidia MFT

9

Przechwytuję pulpit za pomocą DesktopDuplication API i przekształcam próbki z RGBA na NV12 w GPU i karmię to samo sprzętem MediaFoundation H264 MFT. Działa to dobrze z grafiką Nvidia, a także z koderami programowymi, ale kończy się niepowodzeniem, gdy dostępny jest tylko sprzęt graficzny MFT firmy Intel. Kod działa dobrze na tej samej maszynie graficznej Intel, jeśli przejdę do Software MFT. Zapewniłem również, że kodowanie odbywa się sprzętowo na komputerach graficznych Nvidia.

W przypadku grafiki Intel MFT zwraca błąd MEError ( „Nieokreślony błąd” ), co dzieje się dopiero po podaniu pierwszej próbki, a kolejne wywołania ProcessInput (gdy generator zdarzeń wyzwala METransformNeedInput) zwraca Odbiorca obecnie nie przyjmuje dalszych danych wejściowych” . Rzadko zdarza się, że MFT zużywa jeszcze kilka próbek przed zwróceniem tych błędów. To zachowanie jest mylące, karmię próbkę tylko wtedy, gdy generator zdarzeń wyzwala METransformNeedInput asynchronicznie przez IMFAsyncCallback, a także sprawdzam, czy METransformHaveOutput jest wyzwalany natychmiast po podaniu próbki. To naprawdę mnie zaskakuje, gdy ta sama logika asynchroniczna działa dobrze ze sprzętowymi koderami oprogramowania MFT i Microsoft firmy Nvidia.

Istnieje również podobne nierozwiązane pytanie na samym forum wywiadowczym. Mój kod jest podobny do kodu wymienionego w wątku Intel, z tym wyjątkiem, że ustawiam także menedżera urządzeń d3d na koder, jak poniżej.

Istnieją również trzy inne wątki przepełnienia stosu zgłaszające podobny problem bez podania rozwiązania ( koder MFTransform-> ProcessInput zwraca E_FAIL i jak utworzyć IMFSample z tekstury D11 dla enkodera Intel MFT i asynchroniczny MFT nie wysyła zdarzenia MFTransformHaveOutput (dekoder sprzętowy MJPEG Intel MFT) ). Wypróbowałem każdą możliwą opcję bez poprawy.

Kod konwertera kolorów jest pobierany z próbek Intel Media SDK. Przesłałem również tutaj mój pełny kod .

Metoda ustawienia menedżera 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;
}

Implementacja wywołania zwrotnego asynchronicznego:

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;
};

Wygeneruj przykładową metodę:

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;
}

Utwórz próbkę wideo i konwersję kolorów:

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;
}

Sterownik grafiki Intel w maszynie jest już aktualny.

wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj

Przez cały czas wyzwalane jest tylko zdarzenie TransformNeedInput, ale koder skarży się, że nie może zaakceptować żadnych danych wejściowych. Zdarzenie TransformHaveOutput nigdy nie zostało wyzwolone.

wprowadź opis zdjęcia tutaj

Podobne problemy zgłaszane na forach Intel i msdn: 1) https://software.intel.com/en-us/forums/intel-media-sdk/topic/607189 2) https://social.msdn.microsoft.com/ Fora / SECURITY / en-US / fe051dd5-b522-4e4b-9cbb-2c06a5450e40 / imfsinkwriter-merit-validation-failed-for-mft-intel-quick-sync-video-h264-encoder-mft? Forum = mediafoundationdevelopment

Aktualizacja: Próbowałem wyśmiewać tylko źródło wejściowe (programowo tworząc próbkę animowanego prostokąta NV12), pozostawiając wszystko inne nietknięte. Tym razem koder Intel nic nie narzeka, mam nawet próbki wyjściowe. Z wyjątkiem faktu, że wyjściowe wideo z kodera Intel jest zniekształcone, podczas gdy koder Nvidia działa doskonale.

Ponadto nadal pojawia się błąd ProcessInput dla mojego oryginalnego źródła NV12 z koderem Intel. Nie mam problemów z Nvidią MFT i koderami oprogramowania.

Wyjście sprzętowego MFT Intela: (Proszę spojrzeć na dane wyjściowe kodera Nvidia) wprowadź opis zdjęcia tutaj

Dane wyjściowe sprzętu Nvidia MFT: wprowadź opis zdjęcia tutaj

Statystyki użytkowania grafiki Nvidii: wprowadź opis zdjęcia tutaj

Statystyki wykorzystania grafiki Intel (nie rozumiem, dlaczego silnik GPU jest wyświetlany jako dekodowanie wideo): wprowadź opis zdjęcia tutaj

Baran
źródło
Nie pokazano odpowiedniego kodu. Prawdopodobne jest, że coś pójdzie nie tak dokładnie w związku z otrzymywaniem „potrzeby wprowadzania” i zapewnianiem go ProcessInput.
Roman R.
@RomanR. w takim przypadku mogłoby to również nie powieść się w przypadku oprogramowania i MFT sprzętu Nvidia, prawda? Nie pokazałem żadnego kodu związanego z wyliczaniem MFT oraz konfiguracji wejściowych i wyjściowych, ponieważ będzie on zbędny, niepotrzebny i zbyt długi dla wątku, ponieważ wspomniałem, że zastosowałem dokładnie ten sam kod podany na forum wywiadowczym ( software.intel.com / en-us / forums / intel-media-sdk / topic / 681571 ). Spróbuję zaktualizować ten wątek o niezbędne bloki kodu.
Ram
Nie, nie jest. Sprzętowe MFT AMD, Intel i NVIDIA implementują się podobnie, ale jednocześnie zachowują się nieco inaczej. Wszystkie trzy działają głównie jako asynchroniczne MFT, więc twoje pytanie jest wyraźną wskazówką, że robisz coś złego. Bez kodu to tylko zgadywanie, co dokładnie. Koder oprogramowania Microsoft jest zsynchronizowany z MFT AFAIR, więc jest całkiem prawdopodobne, że to część komunikacji z asynchronicznym MFT jest tam, gdzie coś jest nie w porządku.
Roman R.
BTW kod z tego linku do forum Intela działa dla mnie i produkuje wideo.
Roman R.
@RomanR. Zaktualizowałem wątek za pomocą mojej implementacji IMFAsyncCallback, tworzenia próbek i konwersji kolorów, ProcessInput i ProcessOutput. Konwerter kolorów jest po prostu pobierany stąd ( github.com/NVIDIA/video-sdk-samples/blob/master/… ).
Ram

Odpowiedzi:

2

Spojrzałem na twój kod.

Zgodnie z Twoim postem podejrzewam problem z procesorem wideo Intel.

Mój system operacyjny to Win7, więc postanowiłem przetestować zachowanie procesora wideo za pomocą urządzenia D3D9Device na mojej karcie Nvidia, a następnie na karcie graficznej Intel HD Graphics 4000.

Podejrzewam, że możliwości procesora wideo będą zachowywać się tak samo w przypadku urządzenia D3D9Device, jak i urządzenia D3D11Device. Oczywiście konieczne będzie sprawdzenie.

Zrobiłem więc ten program do sprawdzenia: https://github.com/mofo7777/DirectXVideoScreen (patrz podprojekt D3D9VideoProcessor)

Wygląda na to, że nie sprawdzasz wystarczających informacji na temat możliwości procesora wideo.

Dzięki IDXVAHD_Device :: GetVideoProcessorDeviceCaps oto, co sprawdzam:

DXVAHD_VPDEVCAPS.MaxInputStreams> 0

DXVAHD_VPDEVCAPS.VideoProcessorCount> 0

DXVAHD_VPDEVCAPS.OutputFormatCount> 0

DXVAHD_VPDEVCAPS.InputFormatCount> 0

DXVAHD_VPDEVCAPS.InputPool == D3DPOOL_DEFAULT

Sprawdzam także format wejściowy i wyjściowy obsługiwany przez IDXVAHD_Device :: GetVideoProcessorOutputFormats i IDXVAHD_Device :: GetVideoProcessorInputFormats.

Tutaj znalazłem różnicę między procesorem graficznym Nvidia a procesorem Intel.

NVIDIA: 4 format wyjściowy

  • D3DFMT_A8R8G8B8
  • D3DFMT_X8R8G8B8
  • D3DFMT_YUY2
  • D3DFMT_NV12

INTEL: 3 format wyjściowy

  • D3DFMT_A8R8G8B8
  • D3DFMT_X8R8G8B8
  • D3DFMT_YUY2

W przypadku Intel HD Graphics 4000 nie ma obsługi formatu wyjściowego NV12.

Również, aby program działał poprawnie, muszę ustawić stan strumienia przed użyciem 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

Dla 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

Czy możesz najpierw zweryfikować możliwości procesora wideo twojego GPU? Czy widzisz taką samą różnicę jak ja?

To jest pierwsza rzecz, którą musimy wiedzieć, i wydaje się, że twój program tego nie sprawdza, z tego, co widziałem w twoim projekcie github.

mofo77
źródło
Masz rację. GetVideoProcessorOutputFormats na grafice Intela zwróciło tylko warianty RGB i YUY2.
Ram
Jestem w stanie łatwo przekonwertować teksturę RGBA na YUY2 na procesorach Intel. Ale haczyk jest, wydaje się, że grafika Intel obsługuje tylko format wejściowy NV12. Teraz konwerter kolorów i koder wideo są niezgodne. Nadal zastanawiam się, dlaczego Intel postanowił zrobić to w ten sposób. Czy istnieje inny sposób na wydajną konwersję RGB na NV12 ?. Próbowałem już podejść programowych, które nie zapewniają odpowiedniej wydajności.
Ram
Masz moduł cieniujący lub moduł obliczeniowy.
mofo77,
1
Pracuję nad podejściem cieniującym. Sprawdź github.com/mofo7777/DirectXVideoScreen pod kątem aktualizacji.
mofo77,
Świetny! Dzięki za udostępnienie. To naprawdę pomocne.
Ram
1

Jak wspomniano w poście, błąd MEError („Błąd nieokreślony”) został zwrócony przez generator zdarzeń Transforma natychmiast po podaniu pierwszej próbki wejściowej na sprzęcie Intela, a kolejne wywołania właśnie zwróciły „Transform Potrzebują więcej danych wejściowych”, ale nie wygenerowano danych wyjściowych . Ten sam kod działał dobrze na maszynach Nvidii. Po wielu eksperymentach i badaniach, zorientowałem się, że tworzę zbyt wiele instancji D3d11Device. W moim przypadku stworzyłem 2 do 3 urządzeń do przechwytywania, konwersji kolorów i kodera sprzętowego. Mógłbym po prostu ponownie użyć pojedynczej instancji D3dDevice. Jednak tworzenie wielu instancji D3d11Device może działać na komputerach z wyższej półki. Nigdzie nie jest to udokumentowane. Nie mogłem znaleźć nawet wskazówki co do przyczyn błędu „MEError”. Nigdzie nie wspomniano.

Ponowne użycie instancji D3D11Device rozwiązało problem. Opublikowanie tego rozwiązania, ponieważ może być pomocne dla osób, które borykają się z tym samym problemem co mój.

Baran
źródło
Nie widzę w twoim poście, w którym wspomniany jest błąd E_UNEXPECTED ...
mofo77
@ mofo77, przepraszam, to MEError = 1 („Nieokreślony błąd”), jak wspomniano w poście. Trochę oszalałem. Poprawiłem moją odpowiedź. Dzięki za wskazanie.
Ram