인텔 그래픽 하드웨어 H264 MFT 프로세스 몇 개의 입력 샘플을 공급 한 후 입력 호출이 실패합니다. Nvidia 하드웨어 MFT에서도 동일하게 작동합니다.


9

DesktopDuplication API를 사용하여 데스크탑을 캡처하고 GPU에서 샘플을 RGBA에서 NV12로 변환하고 MediaFoundation 하드웨어 H264 MFT에 공급합니다. 이것은 Nvidia 그래픽 및 소프트웨어 인코더에서도 잘 작동하지만 인텔 그래픽 하드웨어 MFT 만 사용할 수 있으면 실패합니다. 소프트웨어 MFT로 폴백하면 동일한 인텔 그래픽 시스템에서 코드가 제대로 작동합니다. 또한 인코딩이 실제로 Nvidia 그래픽 시스템의 하드웨어에서 수행되는지 확인했습니다.

Intel 그래픽에서 MFT는 첫 번째 샘플이 공급 된 직후에만 발생하는 MEError ( " unspecified error" )를 반환 하고, ProcessInput (이벤트 생성기에서 METransformNeedInput을 트리거 할 때)에 대한 후속 호출은 " 수취인 이 현재 추가 입력을 수락하지 않습니다"를 반환합니다. . MFT가 이러한 오류를 반환하기 전에 몇 개의 샘플을 더 소비하는 경우는 드 rare니다. 이 동작은 혼란 스럽습니다. 이벤트 생성기가 IMFAsyncCallback을 통해 METransformNeedInput을 비동기 적으로 트리거 할 때만 샘플을 공급하고 샘플이 공급되는 즉시 METransformHaveOutput이 트리거되는지 여부를 올바르게 확인합니다. Nvidia 하드웨어 MFT 및 Microsoft 소프트웨어 인코더에서 동일한 비동기 논리가 제대로 작동하면 실제로 문제가됩니다.

인텔 포럼 자체 에도 이와 비슷한 해결되지 않은 질문 이 있습니다. 내 코드는 인텔 스레드에서 언급 한 코드와 비슷하지만 d3d 장치 관리자를 아래처럼 인코더로 설정한다는 사실을 제외하고는.

그리고, 주어진 해결책와 유사한 문제를보고 세 가지 다른 스택 오버플로 스레드가있다 ( MFTransform 엔코더 -> ProcessInput가 E_FAIL 반환방법은 인텔 MFT 인코더에 대한 D11 텍스처에서 IMFSample을 만들 & MFTransformHaveOutput 이벤트 (인텔 하드웨어 MJPEG 디코더를 전송하지 비동기 MFT MFT) ). 나는 이것에 대한 개선없이 가능한 모든 옵션을 시도했습니다.

색상 변환기 코드 는 인텔 미디어 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";
    }
}

Getd3d 장치 :

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

컴퓨터의 인텔 그래픽 드라이버가 이미 최신 상태입니다.

여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오

TransformNeedInput 이벤트 만 항상 트리거되지만 인코더는 더 이상 입력을받을 수 없다고 불평합니다. TransformHaveOutput 이벤트가 트리거 된 적이 없습니다.

여기에 이미지 설명을 입력하십시오

인텔 및 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- 인텔-빠른-동기화-비디오 -h264-encoder-mft? forum = mediafoundationdevelopment

업데이트 : 입력 소스 (모니터링 사각형 NV12 샘플을 프로그래밍 방식으로 작성하여)를 모방하려고했지만 나머지는 그대로 두었습니다. 이번에는 인텔 인코더가 아무것도 불평하지 않고 출력 샘플도 얻었습니다. 인텔 엔코더의 출력 비디오가 왜곡되는 반면 Nvidia 엔코더는 완벽하게 작동합니다.

또한 인텔 인코더가있는 원래 NV12 소스에 여전히 ProcessInput 오류가 발생합니다. Nvidia MFT 및 소프트웨어 인코더에 문제가 없습니다.

인텔 하드웨어 MFT의 출력 : (Nvidia 인코더의 출력을 참조하십시오) 여기에 이미지 설명을 입력하십시오

Nvidia 하드웨어 MFT의 출력 : 여기에 이미지 설명을 입력하십시오

Nvidia 그래픽 사용 통계 : 여기에 이미지 설명을 입력하십시오

인텔 그래픽 사용 통계 (GPU 엔진이 비디오 디코딩으로 표시되는 이유를 모르겠습니다) : 여기에 이미지 설명을 입력하십시오


관련 코드가 표시되지 않습니다. "필요한 입력"을 수신하고 제공하는 것과 관련하여 문제가 발생할 수 있습니다 ProcessInput.
Roman R.

@RomanR. 이 경우 소프트웨어 및 Nvidia 하드웨어 MFT에서도 실패했을 수 있습니다. MFT 및 입력 및 출력 구성 열거와 관련된 코드는 표시하지 않았습니다. 왜냐하면 인텔 포럼 ( software.intel.com)에 제공된 것과 동일한 코드를 따랐다 고 언급 했으므로 스레드에 대해 중복되고 불필요하며 너무 오래 걸리기 때문입니다. / en-us / forums / intel-media-sdk / topic / 681571 ). 이 스레드를 필요한 코드 블록으로 업데이트하려고합니다.
Ram

전혀 그렇지 않다. AMD, Intel 및 NVIDIA의 하드웨어 MFT는 동일하지만 약간 다른 동작을 구현합니다. 세 가지 모두 대부분 비동기 MFT로 작동하므로 귀하의 질문은 당신이 뭔가 잘못하고 있다는 명백한 징후입니다. 코드가 없으면 정확히 추측 일뿐입니다. Microsoft의 소프트웨어 인코더는 MFT AFAIR와 동기화되므로 비동기 MFT와 통신하는 데 문제가있을 수 있습니다.
Roman R.

BTW 해당 인텔 포럼 링크의 코드가 저에게 효과적이며 비디오를 제작합니다.
Roman R.

@RomanR. IMFAsyncCallback, 샘플 생성 및 색상 변환, ProcessInput & ProcessOutput 구현으로 스레드를 업데이트했습니다. 색상 변환기는 여기서 간단히 가져옵니다 ( github.com/NVIDIA/video-sdk-samples/blob/master/… ).
Ram

답변:


2

나는 당신의 코드를 보았습니다.

귀하의 게시물에 따르면 인텔 비디오 프로세서 문제가 의심됩니다.

내 OS는 Win7이므로 Nvidia 카드의 D3D9Device를 사용하여 비디오 프로세서 동작을 테스트 한 다음 Intel HD Graphics 4000에서 테스트하기로 결정했습니다.

비디오 프로세서 기능이 D3D11Device와 동일한 방식으로 D3D9Device에서 작동한다고 가정합니다. 물론 확인해야합니다.

그래서이 프로그램을 확인했습니다 : 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

인텔 : 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는 RGB 변형과 YUY2 만 반환했습니다.
Ram

인텔 프로세서에서 RGBA 텍스처를 YUY2로 쉽게 변환 할 수 있습니다. 그러나 인텔 그래픽은 NV12 입력 형식 만 지원하는 것 같습니다. 이제 색상 변환기와 비디오 인코더가 호환되지 않습니다. 인텔이 왜 이런 식으로 결정했는지 궁금합니다. RGB를 NV12로 효율적으로 변환하는 다른 방법이 있습니까? 적절한 성능을 제공하지 않는 소프트웨어 접근 방식을 이미 시도했습니다.
Ram

셰이더 또는 계산 셰이더가 있습니다.
mofo77 2018

1
셰이더 접근을하고 있습니다. github.com/mofo7777/DirectXVideoScreen 에서 업데이트를 확인하십시오 .
mofo77 2018

큰! 공유해 주셔서 감사합니다. 정말 도움이됩니다.
Ram

1

포스트에서 언급했듯이 Intel 하드웨어에서 첫 번째 입력 샘플을 공급 한 직후 Transform 's Event generator에서 오류 MEError ( "지정되지 않은 오류")가 반환되었으며 추가 호출은 "Transform Need more input"을 반환했지만 출력이 생성되지 않았습니다. . 동일한 코드는 Nvidia 머신에서 잘 작동했습니다. 많은 실험과 연구 끝에 D3d11Device 인스턴스를 너무 많이 생성하고 있음을 알았습니다. 필자의 경우 캡처, 색상 변환 및 하드웨어 인코더를 위해 각각 2 ~ 3 개의 장치를 만들었습니다. 반면, 단일 D3dDevice 인스턴스를 재사용 할 수있었습니다. 여러 개의 D3d11Device 인스턴스를 만들면 고급 컴퓨터에서 작동 할 수 있습니다. 이것은 어디에도 문서화되어 있지 않습니다. "MEError"오류의 원인에 대한 단서를 찾을 수 없었습니다. 아무데도 언급되지 않았습니다.

D3D11Device 인스턴스를 재사용하면 문제가 해결되었습니다. 이 솔루션을 내 것과 같은 문제에 직면 한 사람들에게 도움이 될 수 있으므로 게시하십시오.


귀하의 게시물에서 E_UNEXPECTED 오류가 언급 된 곳을 볼 수 없습니다 ...
mofo77

@ mofo77, 죄송합니다. 게시물에 언급 된대로 MEError = 1 ( "지정되지 않은 오류")입니다. 나는 내 마음을 잃어 버렸습니다. 내 대답을 수정했습니다. 지적 해 주셔서 감사합니다.
Ram
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.