Intel grafik donanımı H264 MFT ProcessInput çağrısı, birkaç giriş örneği beslendikten sonra başarısız oluyor, aynı Nvidia donanım MFT ile iyi çalışıyor


9

DesktopDuplication API'sını kullanarak masaüstünü yakalayıp GPU'da RGBA'dan NV12'ye örnekleri dönüştürerek ve MediaFoundation donanım H264 MFT'ye besliyorum. Bu, Nvidia grafikleriyle ve ayrıca yazılım kodlayıcılarıyla da iyi çalışır, ancak yalnızca intel grafik donanımı MFT mevcut olduğunda başarısız olur. Yazılım MFT'ye geri dönersem kod aynı intel grafik makinesinde iyi çalışır. Ayrıca kodlamanın aslında Nvidia grafik makinelerindeki donanımda yapılmasını sağladım.

Intel grafiklerinde MFT , yalnızca ilk örnek beslendikten hemen sonra gerçekleşen MEError'u ( "Belirtilmemiş hata" ) döndürür ve daha sonra ProcessInput'a yapılan çağrılar (olay oluşturucu METransformNeedInput'u tetiklediğinde) "Callee şu anda başka girdi kabul etmiyor" ifadesini döndürür . MFT'nin bu hataları iade etmeden önce birkaç örnek daha kullanması nadirdir. Bu davranış kafa karıştırıcı, yalnızca olay üreteci METransformNeedInput IMFAsyncCallback aracılığıyla eşzamansız olarak tetiklediğinde ve aynı zamanda bir örnek beslenir gönderilmez METransformHaveOutput doğru tetiklenip tetiklenmediğini kontrol ettiğimde bir örnek besliyorum. Aynı asenkron mantık Nvidia donanım MFT ve Microsoft yazılım kodlayıcılarıyla iyi çalıştığında bu gerçekten beni şaşırtıyor.

Intel forumunun kendisinde de benzer bir çözülmemiş soru var . Kodum da aşağıdaki gibi kodlayıcıya d3d aygıt yöneticisi ayarladığım gerçeği dışında, intel iş parçacığında belirtilen ile benzer.

Ayrıca, hiçbir çözüm verilmeden benzer bir sorunu bildiren üç yığın taşma iş parçacığı daha vardır ( MFTransform encoder-> ProcessInput, E_FAIL döndürür & Intel MFT kodlayıcı için D11 dokusundan IMFSample nasıl oluşturulur ve Asenkron MFT, MFTransformHaveOutput Event (Intel Hardware MJPEG Decoder) göndermiyor MFT) ). Bu konuda herhangi bir gelişme olmadan mümkün olan her seçeneği denedim.

Renk dönüştürücü kodu intel media sdk örneklerinden alınır. Ayrıca tam kodumu buraya yükledim .

D3d yöneticisini ayarlama yöntemi:

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

Zaman uyumsuz geri arama uygulaması:

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

Örnek yöntemi üret:

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

Video örneği ve renk dönüşümü oluşturun:

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

Makinedeki intel grafik sürücüsü zaten güncel.

resim açıklamasını buraya girin resim açıklamasını buraya girin resim açıklamasını buraya girin

Yalnızca TransformNeedInput olayı her zaman tetikleniyor, ancak kodlayıcı daha fazla girişi kabul edemediğinden şikayet ediyor. TransformHaveOutput olayı hiç tetiklenmedi.

resim açıklamasını buraya girin

Intel ve msdn forumlarında bildirilen benzer sorunlar: 1) https://software.intel.com/en-us/forums/intel-media-sdk/topic/607189 2) https://social.msdn.microsoft.com/ forum / GÜVENLİK / tr / fe051dd5-b522-4e4b-9cbb-2c06a5450e40 / imfsinkwriter-liyakate doğrulama-başarısız-mft-istihbarat-hızlı senkron-video-h264-kodlayıcı-MFT için? forumu = mediafoundationdevelopment

Güncelleme: Sadece giriş kaynağını alay etmeye çalıştım (programlı olarak animasyonlu bir dikdörtgen NV12 örneği oluşturarak) diğer her şeye dokunulmadan bıraktım. Bu sefer, intel encoder hiçbir şeyden şikayetçi değil, çıktı örnekleri bile aldım. Intel video kodlayıcının çıkış videosunun bozuk olması dışında, Nvidia video kodlayıcı mükemmel çalışıyor.

Ayrıca, intel encoder ile orijinal NV12 kaynağım için hala ProcessInput hatası alıyorum. Nvidia MFT ve yazılım kodlayıcılarıyla ilgili sorunum yok.

Intel donanım MFT çıkışı: (Lütfen Nvidia kodlayıcı çıkışına bakın) resim açıklamasını buraya girin

Nvidia donanım MFT çıkışı: resim açıklamasını buraya girin

Nvidia grafik kullanım istatistikleri: resim açıklamasını buraya girin

Intel grafik kullanım istatistikleri (GPU motorunun neden video kod çözme olarak görüntülendiğini anlamıyorum): resim açıklamasını buraya girin


Alakalı kod gösterilmiyor. "Girdi ihtiyacı" alma ve sağlama konusunda bir şeyler ters gidiyor olabilir ProcessInput.
Roman

@RomanR. bu durumda, yazılım ve Nvidia Donanım MFT'leri için de başarısız olabilirdi, değil mi? Ben tam olarak aynı forumda verilen aynı kodu takip ettiğim gibi bir iş parçacığı için gereksiz, gereksiz ve çok uzun olacak çünkü MFT ve giriş ve çıkış yapılandırmaları numaralandırma ile ilgili herhangi bir kod göstermedim ( software.intel.com / tr-tr / forumlar / intel-media-sdk / topic / 681571 ). Bu konuyu gerekli kod bloklarıyla güncellemeye çalışacağım.
Ram

Hayır öyle değil. AMD, Intel ve NVIDIA'dan donanım MFT'leri benzer şekilde uygulanır, ancak aynı zamanda biraz farklı davranışlar gösterir. Üçü de çoğunlukla asenkron MFT olarak çalışır, bu nedenle sorunuz yanlış bir şey yaptığınızı gösteren açık bir göstergedir. Hiçbir kod olmadan sadece tam olarak ne bir tahmin. Microsoft'un yazılım kodlayıcısı MFT AFAIR'ı senkronize eder, bu yüzden büyük olasılıkla asenkron MFT ile iletişimin bir parçası bir şeylerin iyi olmadığı yerdir.
Roman

BTW Intel forum bağlantısındaki kod benim için çalışıyor ve video üretiyor.
Roman

@RomanR. IMFAsyncCallback, Örnek oluşturma ve Renk dönüştürme, ProcessInput ve ProcessOutput benim uygulama ile iş parçacığı güncelledim. Renk dönüştürücü buradan kolayca alınır ( github.com/NVIDIA/video-sdk-samples/blob/master/… ).
Ram

Yanıtlar:


2

Koduna baktım.

Yayınınıza göre bir Intel video işlemci sorunundan şüpheleniyorum.

İşletim sistemim Win7, bu yüzden video işlemci davranışını Nvidia kartımdaki D3D9Device ve ardından Intel HD Graphics 4000 ile test etmeye karar verdim.

Video işlemci özelliklerinin D3D9Device için D3D11Device ile aynı şekilde davranacağını düşünüyorum. Tabii ki kontrol etmek gerekecek.

Bu yüzden kontrol etmek için bu programı yaptım: https://github.com/mofo7777/DirectXVideoScreen (bkz. D3D9VideoProcessor alt projesi)

Video işlemci özellikleri hakkında yeterli şeyleri kontrol etmediğiniz anlaşılıyor.

IDXVAHD_Device :: GetVideoProcessorDeviceCaps ile kontrol ettiğim şey:

DXVAHD_VPDEVCAPS.MaxInputStreams> 0

DXVAHD_VPDEVCAPS.VideoProcessorCount> 0

DXVAHD_VPDEVCAPS.OutputFormatCount> 0

DXVAHD_VPDEVCAPS.InputFormatCount> 0

DXVAHD_VPDEVCAPS.InputPool == D3DPOOL_DEFAULT

Ayrıca IDXVAHD_Device :: GetVideoProcessorOutputFormats ve IDXVAHD_Device :: GetVideoProcessorInputFormats ile desteklenen giriş ve çıkış formatlarını da kontrol ediyorum.

Nvidia GPU ve Intel GPU arasında bir fark buldum.

NVIDIA: 4 çıkış formatı

  • D3DFMT_A8R8G8B8
  • D3DFMT_X8R8G8B8
  • D3DFMT_YUY2
  • D3DFMT_NV12

INTEL: 3 çıkış formatı

  • D3DFMT_A8R8G8B8
  • D3DFMT_X8R8G8B8
  • D3DFMT_YUY2

Intel HD Graphics 4000'de NV12 çıkış biçimi için destek yoktur.

Ayrıca programın düzgün çalışması için, VideoProcessBltHD kullanmadan önce akış durumunu ayarlamanız gerekir:

  • 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 için:

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

Önce GPU'nuzun video işlemci özelliklerini doğrulayabilir misiniz? Gördüğümle aynı farkı görüyor musunuz?

Bu bilmemiz gereken ilk şey ve programınız github projenizde gördüğüm şeyden bunu kontrol etmiyor gibi görünüyor.


Haklısın. Intel grafiklerindeki GetVideoProcessorOutputFormats yalnızca RGB varyantları ve YUY2 döndürdü.
Ram

Intel işlemcilerde RGBA dokusunu YUY2'ye kolayca dönüştürebiliyorum. Ancak yakalama, Intel grafiklerinin yalnızca NV12 giriş formatını desteklediği anlaşılıyor. Şimdi renk dönüştürücü ve video kodlayıcı uyumsuz. Hala Intel'in neden böyle yapmaya karar verdiğini merak ediyorum. RGB'den NV12'ye dönüşümün verimli bir şekilde yapılmasının başka bir yolu var mı? Zaten yeterli performans sunmayan yazılım yaklaşımlarını denedim.
Ram

Gölgelendiriciniz veya hesaplama gölgelendiriciniz var.
mofo77

1
Gölgelendirici bir yaklaşım üzerinde çalışıyorum. Kontrol github.com/mofo7777/DirectXVideoScreen güncellemesi için.
mofo77

Harika! Paylaştığınız için teşekkürler, gerçekten yararlı.
Ram

1

Mesajda belirtildiği gibi, Intel donanımındaki ilk giriş örneğini besledikten hemen sonra MEError ("Belirtilmeyen hata") hatası Transform'un Olay üreteci tarafından döndürüldü ve daha fazla çağrı sadece "Dönüştürme Daha fazla girişe ihtiyaç duydu" döndürüldü, ancak çıktı üretilmedi . Yine de aynı kod Nvidia makinelerinde iyi çalıştı. Çok denedikten ve araştırdıktan sonra, D3d11Device'in çok fazla örneğini oluşturduğumu anladım, Benim durumumda, sırasıyla Yakalama, renk dönüştürme ve Donanım kodlayıcı için 2 ila 3 cihaz oluşturdum. Oysa tek bir D3dDevice örneğini yeniden kullanabilirdim. Birden çok D3d11Device örneği oluşturmak, üst düzey makinelerde çalışabilir. Bu hiçbir yerde belgelenmemiştir. "MEError" hatasının nedenleri hakkında bir ipucu bile bulamadım. Hiç bir yerde bahsedilmiyor.

D3D11Device örneğinin yeniden kullanılması sorunu çözdü. Bu çözümü, benimkiyle aynı sorunla karşılaşan insanlar için yararlı olabileceği için göndermek.


Mesajınızda E_UNEXPECTED hatasının nerede belirtildiğini görmüyorum ...
mofo77

@ mofo77, Üzgünüz, yayında belirtildiği gibi MEError = 1 ("Belirtilmemiş hata") idi. Aklımı kaybettim. Cevabım düzeltildi. İşaret ettiğiniz için teşekkürler.
Ram
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.