Der Aufruf der Intel-Grafikhardware H264 MFT ProcessInput schlägt fehl, nachdem nur wenige Eingabebeispiele eingegeben wurden. Dies funktioniert auch mit der Nvidia-Hardware-MFT

9

Ich erfasse den Desktop mithilfe der DesktopDuplication-API, konvertiere die Beispiele von RGBA in NV12 in der GPU und speise sie in die MediaFoundation-Hardware H264 MFT ein. Dies funktioniert gut mit Nvidia-Grafiken und auch mit Software-Encodern, schlägt jedoch fehl, wenn nur Intel-Grafikhardware MFT verfügbar ist. Der Code funktioniert auf derselben Intel-Grafikmaschine einwandfrei, wenn ich auf Software MFT zurückgreife. Ich habe auch sichergestellt, dass die Codierung tatsächlich in Hardware auf Nvidia-Grafikmaschinen erfolgt.

Bei Intel-Grafiken gibt MFT MEError ( "Nicht spezifizierter Fehler" ) zurück, was unmittelbar nach dem Einspeisen des ersten Samples auftritt, und nachfolgende Aufrufe von ProcessInput (wenn der Ereignisgenerator METransformNeedInput auslöst) geben "Der Angerufene akzeptiert derzeit keine weiteren Eingaben" zurück . Es ist selten, dass MFT einige weitere Proben verbraucht, bevor diese Fehler zurückgegeben werden. Dieses Verhalten ist verwirrend. Ich füttere ein Sample nur, wenn der Ereignisgenerator METransformNeedInput asynchron über IMFAsyncCallback auslöst, und überprüfe auch ordnungsgemäß, ob METransformHaveOutput ausgelöst wird, sobald ein Sample gespeist wird. Das verwirrt mich wirklich, wenn dieselbe asynchrone Logik mit Nvidia-Hardware-MFT- und Microsoft-Software-Encodern einwandfrei funktioniert.

Es gibt auch eine ähnliche ungelöste Frage im Intel-Forum. Mein Code ähnelt dem im Intel-Thread erwähnten, außer dass ich auch den d3d-Geräte-Manager wie unten auf den Encoder setze.

Und, gibt es drei weitere Stapelüberlauf - Threads ein ähnliches Problem ohne Lösung gegeben Berichterstattung ( MFTransform Encoder-> Process E_Fail & Wie IMFSample von D11 Textur für Intel MFT - Encoder erstellen und Asynchronous MFT nicht MFTransformHaveOutput Ereignis (Intel Hardware MJPEG Decoder zu senden MFT) ). Ich habe jede mögliche Option ausprobiert, ohne dies zu verbessern.

Der Farbkonvertercode stammt aus Intel Media SDK-Beispielen. Ich habe auch meinen kompletten Code hochgeladen hier .

Methode zum Festlegen des d3d-Managers:

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

Asynchrone Rückrufimplementierung:

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

Beispielmethode generieren:

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

Videobeispiel und Farbkonvertierung erstellen:

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

Der Intel-Grafiktreiber im Computer ist bereits auf dem neuesten Stand.

Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

Nur das TransformNeedInput-Ereignis wird ständig ausgelöst, der Encoder beschwert sich jedoch, dass er keine weiteren Eingaben akzeptieren kann. Das TransformHaveOutput-Ereignis wurde nie ausgelöst.

Geben Sie hier die Bildbeschreibung ein

Ähnliche Probleme wurden in Intel & msdn-Foren gemeldet: 1) https://software.intel.com/en-us/forums/intel-media-sdk/topic/607189 2) https://social.msdn.microsoft.com/ Foren / SICHERHEIT / de-US / fe051dd5-b522-4e4b-9cbb-2c06a5450e40 / Imfsinkwriter-Merit-Validierung-fehlgeschlagen-für-Mft-Intel-Quick-Sync-Video-H264-Encoder-Mft? Forum = Mediafoundation-Entwicklung

Update: Ich habe versucht, nur die Eingabequelle zu verspotten (indem ich programmgesteuert ein animierendes Rechteck-NV12-Beispiel erstellt habe), wobei alles andere unberührt blieb. Diesmal beschwert sich der Intel-Encoder nicht, ich habe sogar Ausgangsbeispiele. Abgesehen von der Tatsache, dass das Ausgangsvideo des Intel-Encoders verzerrt ist, während der Nvidia-Encoder einwandfrei funktioniert.

Außerdem wird immer noch der ProcessInput-Fehler für meine ursprüngliche NV12-Quelle mit Intel-Encoder angezeigt. Ich habe keine Probleme mit Nvidia MFT und Software-Encodern.

Ausgabe von Intel Hardware MFT: (Bitte sehen Sie sich die Ausgabe des Nvidia-Encoders an.) Geben Sie hier die Bildbeschreibung ein

Ausgabe von Nvidia Hardware MFT: Geben Sie hier die Bildbeschreibung ein

Nutzungsstatistiken für Nvidia-Grafiken: Geben Sie hier die Bildbeschreibung ein

Intel-Grafiknutzungsstatistiken (ich verstehe nicht, warum die GPU-Engine als Videodecodierung angezeigt wird): Geben Sie hier die Bildbeschreibung ein

RAM
quelle
Kein relevanter Code angezeigt. Es ist wahrscheinlich, dass etwas schief geht, wenn "Bedarfseingabe" empfangen und bereitgestellt wird ProcessInput.
Roman R.
@ RomanR. Wenn dies der Fall ist, könnte es auch für Software- und Nvidia-Hardware-MFTs fehlgeschlagen sein, nicht wahr? Ich habe keinen Code für die Aufzählung von MFT- und Eingabe- und Ausgabekonfigurationen angezeigt, da dieser für einen Thread redundant, unnötig und zu lang ist, da ich erwähnt habe, dass ich genau den gleichen Code befolgt habe, der im Intel-Forum ( software.intel.com) angegeben wurde / de-de / forums / intel-media-sdk / topic / 681571 ). Ich werde versuchen, diesen Thread mit den erforderlichen Codeblöcken zu aktualisieren.
Ram
Nein ist es nicht. Hardware-MFTs von AMD, Intel und NVIDIA implementieren gleichermaßen, verhalten sich aber gleichzeitig leicht unterschiedlich. Alle drei arbeiten meistens als asynchrone MFTs, sodass Ihre Frage ein offensichtlicher Hinweis darauf ist, dass Sie etwas falsch machen. Ohne Code ist es nur eine Vermutung, was genau. Der Software-Encoder von Microsoft ist MFT AFAIR synchronisieren. Daher ist es sehr wahrscheinlich, dass bei der Kommunikation mit asynchronem MFT etwas nicht in Ordnung ist.
Roman R.
Übrigens funktioniert der Code von diesem Intel-Forum-Link für mich und produziert Videos.
Roman R.
@ RomanR. Ich habe den Thread mit meiner Implementierung von IMFAsyncCallback, Beispielerstellung und Farbkonvertierung, ProcessInput & ProcessOutput aktualisiert. Der Farbkonverter wird einfach von hier übernommen ( github.com/NVIDIA/video-sdk-samples/blob/master/… ).
Ram

Antworten:

2

Ich habe mir deinen Code angesehen.

Laut Ihrem Beitrag vermute ich ein Intel-Videoprozessor-Problem.

Mein Betriebssystem ist Win7, daher entscheide ich mich, das Verhalten des Videoprozessors mit einem D3D9Device auf meiner Nvidia-Karte und dann auf einem Intel HD Graphics 4000 zu testen.

Ich nehme an, dass sich die Videoprozessorfunktionen für ein D3D9-Gerät genauso verhalten wie für ein D3D11-Gerät. Natürlich muss dies überprüft werden.

Also habe ich dieses Programm gemacht, um Folgendes zu überprüfen: https://github.com/mofo7777/DirectXVideoScreen (siehe D3D9VideoProcessor-Unterprojekt)

Anscheinend überprüfen Sie nicht genügend Informationen über die Funktionen des Videoprozessors.

Mit IDXVAHD_Device :: GetVideoProcessorDeviceCaps überprüfe ich Folgendes:

DXVAHD_VPDEVCAPS.MaxInputStreams> 0

DXVAHD_VPDEVCAPS.VideoProcessorCount> 0

DXVAHD_VPDEVCAPS.OutputFormatCount> 0

DXVAHD_VPDEVCAPS.InputFormatCount> 0

DXVAHD_VPDEVCAPS.InputPool == D3DPOOL_DEFAULT

Ich überprüfe auch das Eingabe- und Ausgabeformat, das von IDXVAHD_Device :: GetVideoProcessorOutputFormats und IDXVAHD_Device :: GetVideoProcessorInputFormats unterstützt wird.

Hier habe ich einen Unterschied zwischen Nvidia GPU und Intel GPU gefunden.

NVIDIA: 4 Ausgabeformat

  • D3DFMT_A8R8G8B8
  • D3DFMT_X8R8G8B8
  • D3DFMT_YUY2
  • D3DFMT_NV12

INTEL: 3 Ausgabeformat

  • D3DFMT_A8R8G8B8
  • D3DFMT_X8R8G8B8
  • D3DFMT_YUY2

Unter Intel HD Graphics 4000 wird das NV12-Ausgabeformat nicht unterstützt.

Damit das Programm ordnungsgemäß funktioniert, muss der Stream-Status eingerichtet werden, bevor VideoProcessBltHD verwendet werden kann:

  • 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

Für 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

Könnten Sie zuerst die Videoprozessorfunktionen Ihrer GPU überprüfen? Sehen Sie den gleichen Unterschied wie ich?

Dies ist das erste, was wir wissen müssen, und es scheint, dass Ihr Programm dies nicht überprüft, wie ich es in Ihrem Github-Projekt gesehen habe.

mofo77
quelle
Du hast recht. GetVideoProcessorOutputFormats für Intel-Grafiken gab nur RGB-Varianten und YUY2 zurück.
Ram
Ich kann die RGBA-Textur auf Intel-Prozessoren problemlos in YUY2 konvertieren. Der Haken ist jedoch, dass Intel-Grafiken anscheinend nur das NV12-Eingabeformat unterstützen. Jetzt sind Farbkonverter und Videocodierer nicht mehr kompatibel. Ich frage mich immer noch, warum Intel beschlossen hat, es so zu machen. Gibt es eine andere Möglichkeit, die Konvertierung von RGB in NV12 effizient durchzuführen? Ich habe bereits Software-Ansätze ausprobiert, die keine ausreichende Leistung bieten.
Ram
Sie haben Shader oder Compute Shader.
mofo77
1
Ich arbeite an einem Shader-Ansatz. Überprüfen Sie github.com/mofo7777/DirectXVideoScreen auf Aktualisierungen.
mofo77
Großartig! Danke fürs Teilen, es ist wirklich hilfreich.
Ram
1

Wie im Beitrag erwähnt, wurde der Fehler MEError ("Nicht spezifizierter Fehler") vom Ereignisgenerator von Transform unmittelbar nach dem Einspeisen des ersten Eingabebeispiels auf Intel-Hardware zurückgegeben, und weitere Aufrufe gaben nur "Transform Need more input" zurück, aber es wurde keine Ausgabe erzeugt . Der gleiche Code funktionierte jedoch auf Nvidia-Computern einwandfrei. Nachdem ich viel experimentiert und recherchiert hatte, stellte ich fest, dass ich zu viele Instanzen von D3d11Device erstellt habe. In meinem Fall habe ich 2 bis 3 Geräte für die Erfassung, Farbkonvertierung bzw. den Hardware-Encoder erstellt. Ich hätte einfach eine einzelne D3dDevice-Instanz wiederverwenden können. Das Erstellen mehrerer D3d11Device-Instanzen funktioniert jedoch möglicherweise auf High-End-Computern. Dies ist nirgendwo dokumentiert. Ich konnte nicht einmal einen Hinweis auf die Ursachen des "MEError" -Fehlers finden. Es wird nirgendwo erwähnt.

Die Wiederverwendung der D3D11Device-Instanz löste das Problem. Das Posten dieser Lösung kann hilfreich sein für Personen, die mit demselben Problem wie ich konfrontiert sind.

RAM
quelle
Ich sehe nicht in Ihrem Beitrag, wo der E_UNEXPECTED-Fehler erwähnt wird ...
mofo77
@ mofo77, Entschuldigung, es war MEError = 1 ("Nicht spezifizierter Fehler"), wie im Beitrag erwähnt. Ich habe irgendwie den Verstand verloren. Meine Antwort wurde korrigiert. Vielen Dank für den Hinweis.
Ram