Cuộc gọi xử lý phần cứng đồ họa Intel H264 MFT ProcessInput không thành công sau khi cung cấp một vài mẫu đầu vào, hoạt động tương tự với MFT của phần cứng Nvidia


9

Tôi đang chụp máy tính để bàn bằng API DesktopD repeatation và chuyển đổi các mẫu từ RGBA sang NV12 trong GPU và cung cấp tương tự cho phần cứng MediaFoundation H264 MFT. Điều này hoạt động tốt với đồ họa Nvidia và cũng với bộ mã hóa phần mềm nhưng không thành công khi chỉ có phần cứng đồ họa intel MFT. Mã này hoạt động tốt trên cùng một máy đồ họa intel nếu tôi dự phòng Phần mềm MFT. Tôi cũng đã đảm bảo rằng mã hóa thực sự được thực hiện trong phần cứng trên các máy đồ họa Nvidia.

Trên đồ họa Intel, MFT trả về MEError ( "Lỗi không xác định" ), chỉ xảy ra sau khi mẫu đầu tiên được cung cấp và các cuộc gọi tiếp theo tới ProcessInput (khi trình tạo sự kiện METransformNeedInput) trả về "Hiện tại callee không chấp nhận đầu vào tiếp theo" . Thật hiếm khi MFT tiêu thụ thêm một vài mẫu trước khi trả lại các lỗi này. Hành vi này gây nhầm lẫn, tôi chỉ cho ăn một mẫu khi trình tạo sự kiện kích hoạt METransformNeedInput không đồng bộ thông qua IMFAsyncCallback và cũng kiểm tra chính xác liệu METransformHaveOutput có được kích hoạt ngay khi mẫu được cung cấp hay không. Điều này thực sự gây trở ngại cho tôi khi logic không đồng bộ tương tự hoạt động tốt với bộ mã hóa phần mềm MFT & Microsoft của phần cứng Nvidia.

Ngoài ra còn có một câu hỏi chưa được giải quyết tương tự trong chính diễn đàn intel. Mã của tôi tương tự như mã được đề cập trong luồng intel, ngoại trừ thực tế là tôi cũng đang đặt trình quản lý thiết bị d3d cho bộ mã hóa như bên dưới.

Và, có ba luồng tràn ngăn xếp khác báo cáo một vấn đề tương tự mà không có giải pháp nào được đưa ra ( Bộ mã hóa MFTransform-> ProcessInput trả về E_FAIL & Cách tạo IMFSample từ kết cấu D11 cho bộ mã hóa MFT của Intel & MFT không đồng bộ MFT không gửi MFTransformHaveOutput MFT) ). Tôi đã thử mọi lựa chọn có thể mà không cải thiện điều này.

Mã chuyển đổi màu được lấy từ các mẫu sdk phương tiện truyền thông intel. Tôi cũng đã tải lên mã hoàn chỉnh của tôi ở đây .

Phương pháp đặt trình quản lý 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;
}

Thực hiện gọi lại Async:

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

Tạo phương thức mẫu:

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

Tạo mẫu video và chuyển đổi màu:

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

Trình điều khiển đồ họa intel trong máy đã được cập nhật.

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Chỉ có sự kiện TransformNeedInput được kích hoạt mọi lúc nhưng bộ mã hóa phàn nàn rằng nó không thể chấp nhận bất kỳ đầu vào nào nữa. Sự kiện TransformHaveOutput chưa bao giờ được kích hoạt.

nhập mô tả hình ảnh ở đây

Các vấn đề tương tự được báo cáo trên các diễn đàn intel & msdn: 1) https://software.intel.com/en-us/forums/intel-media-sdk/topic/607189 2) https://social.msdn.microsoft.com/ Diễn đàn / BẢO MẬT / en-US / fe051dd5-b522-4e4b-9cbb-2c06a5450e40 / imfsinkwriter-merit-verify-fail-for-mft-intel-quick-sync-video-h264-enc

Cập nhật: Tôi đã cố gắng giả định chỉ nguồn đầu vào (Bằng cách lập trình tạo một mẫu NV12 hình chữ nhật hoạt hình) để mọi thứ khác không bị ảnh hưởng. Lần này, bộ mã hóa intel không phàn nàn bất cứ điều gì, tôi thậm chí còn có các mẫu đầu ra. Ngoại trừ thực tế là video đầu ra của bộ mã hóa intel bị méo trong khi bộ mã hóa Nvidia hoạt động hoàn toàn tốt.

Hơn nữa, tôi vẫn nhận được lỗi ProcessInput cho nguồn NV12 ban đầu của mình với bộ mã hóa intel. Tôi không có vấn đề với Nvidia MFT và bộ mã hóa phần mềm.

Đầu ra của phần cứng Intel MFT: (Vui lòng xem đầu ra của bộ mã hóa Nvidia) nhập mô tả hình ảnh ở đây

Đầu ra của phần cứng Nvidia MFT: nhập mô tả hình ảnh ở đây

Số liệu thống kê sử dụng đồ họa của Nvidia: nhập mô tả hình ảnh ở đây

Số liệu thống kê sử dụng đồ họa của Intel (Tôi không hiểu tại sao công cụ GPU được hiển thị dưới dạng giải mã video): nhập mô tả hình ảnh ở đây


Không có mã liên quan được hiển thị. Có khả năng một cái gì đó sai chính xác xung quanh việc nhận "cần đầu vào" và cung cấp cho nó ProcessInput.
Roman R.

@RomanR. nếu đó là trường hợp, nó cũng có thể đã thất bại đối với MFTs phần cứng & Nvidia, phải không? Tôi chưa hiển thị bất kỳ mã nào liên quan đến việc liệt kê MFT và cấu hình đầu vào và đầu ra bởi vì nó sẽ là dự phòng, không cần thiết và quá dài cho một chủ đề như tôi đã đề cập rằng tôi đã theo dõi chính xác cùng một mã được đưa ra trong diễn đàn intel ( software.intel.com / en-us / forum / intel-media-sdk / topic / 681571 ). Tôi sẽ cố gắng cập nhật chủ đề này với các khối mã cần thiết.
Ram

Không có nó không phải là. Các MFT phần cứng của AMD, Intel và NVIDIA thực hiện giống nhau nhưng đồng thời hành vi hơi khác nhau. Tất cả ba chủ yếu hoạt động như các MFT không đồng bộ vì vậy câu hỏi của bạn là một dấu hiệu rõ ràng cho thấy bạn đang làm gì đó sai. Không có mã, nó chỉ là một phỏng đoán chính xác. Bộ mã hóa phần mềm của Microsoft được đồng bộ hóa MFT AFAIR, do đó rất có thể đó là một phần của việc giao tiếp với asFT MFT là nơi không ổn.
Roman R.

Mã BTW từ liên kết diễn đàn Intel đó hoạt động với tôi và tạo video.
Roman R.

@RomanR. Tôi đã cập nhật chủ đề với việc triển khai IMFAsyncCallback, Tạo mẫu và chuyển đổi màu, ProcessInput & ProcessOutput. Bộ chuyển đổi màu chỉ đơn giản được lấy từ đây ( github.com/NVIDIA/video-sdk-samples/blob/master/, ).
Ram

Câu trả lời:


2

Tôi nhìn vào mã của bạn.

Theo bài đăng của bạn, tôi nghi ngờ có vấn đề về bộ xử lý video của Intel.

Hệ điều hành của tôi là Win7, vì vậy tôi quyết định kiểm tra hành vi của bộ xử lý video với D3D9Device trên thẻ Nvidia của tôi và sau đó trên Intel HD Graphics 4000.

Tôi cho rằng các khả năng của bộ xử lý video sẽ hoạt động theo cách tương tự đối với D3D9Device như đối với D3D11Device. Tất nhiên sẽ cần phải kiểm tra.

Vì vậy, tôi đã thực hiện chương trình này để kiểm tra: https://github.com/mofo7777/DirectXVideoScreen (xem tiểu dự án D3D9VideoProcessor)

Có vẻ như bạn không kiểm tra đủ thứ về khả năng của bộ xử lý video.

Với IDXVAHD_Device :: GetVideoProcessorDeviceCaps, đây là những gì tôi kiểm tra:

DXVAHD_VPDEVCAPS.MaxInputStreams> 0

DXVAHD_VPDEVCAPS.VideoProcessorCount> 0

DXVAHD_VPDEVCAPS.OutputFormatCount> 0

DXVAHD_VPDEVCAPS.InputFormatCount> 0

DXVAHD_VPDEVCAPS.InputPool == D3DPOOL_DEFAULT

Tôi cũng kiểm tra định dạng đầu vào và đầu ra được hỗ trợ với IDXVAHD_Device :: GetVideoProcessorOutputFormats và IDXVAHD_Device :: GetVideoProcessorInputFormats.

Đây là nơi tôi tìm thấy sự khác biệt giữa GPU Nvidia và GPU Intel.

NVIDIA: 4 định dạng đầu ra

  • D3DFMT_A8R8G8B8
  • D3DFMT_X8R8G8B8
  • D3DFMT_YUY2
  • D3DFMT_NV12

INTEL: 3 định dạng đầu ra

  • D3DFMT_A8R8G8B8
  • D3DFMT_X8R8G8B8
  • D3DFMT_YUY2

Trên Intel HD Graphics 4000, không hỗ trợ định dạng đầu ra NV12.

Ngoài ra để chương trình hoạt động chính xác, tôi cần thiết lập trạng thái luồng trước khi sử dụng VideoProcessBltHD:

  • DXVAHD_STREAM_STATE_D3DFORMAT
  • DXVAHD_STREAM_STATE_FRAME_FORMAT
  • DXVAHD_STREAM_STATE_INPUT_COLORinksACE
  • DXVAHD_STREAM_STATE_SOURCE_RECT
  • DXVAHD_STREAM_STATE_DESTINATION_RECT

Dành cho 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

Trước tiên, bạn có thể xác minh khả năng xử lý video của GPU không. Bạn có thấy sự khác biệt như tôi thấy không?

Đây là điều đầu tiên chúng ta cần biết và dường như chương trình của bạn không kiểm tra điều này, từ những gì tôi đã thấy trong dự án github của bạn.


Bạn đúng rồi. GetVideoProcessorOutputFormats trên đồ họa Intel chỉ trả về các biến thể RGB và YUY2.
Ram

Tôi có thể dễ dàng chuyển đổi kết cấu RGBA thành YUY2 trên bộ xử lý Intel. Nhưng điều thú vị là, dường như đồ họa Intel chỉ hỗ trợ định dạng đầu vào NV12. Bây giờ bộ chuyển đổi màu và bộ mã hóa video không tương thích. Tôi vẫn đang tự hỏi tại sao Intel quyết định làm cho nó như thế này. Có cách nào khác để chuyển đổi RGB sang NV12 hiệu quả không?. Tôi đã thử các cách tiếp cận phần mềm không cung cấp hiệu suất đầy đủ.
Ram

Bạn có shader hoặc tính toán shader.
mofo77

1
Tôi đang làm việc theo cách tiếp cận shader. Kiểm tra github.com/mofo7777/DirectXVideoScreen để cập nhật.
mofo77

Tuyệt quá! Cảm ơn đã chia sẻ, nó thực sự hữu ích.
Ram

1

Như đã đề cập trong bài đăng, lỗi MEError ("Lỗi không xác định") đã được trình tạo Sự kiện của Transform trả về ngay sau khi cung cấp mẫu đầu vào đầu tiên trên phần cứng của Intel và, các cuộc gọi tiếp theo chỉ trả về "Biến đổi cần thêm đầu vào", nhưng không có đầu ra nào được tạo ra . Mã tương tự hoạt động tốt trên các máy Nvidia. Sau khi thử nghiệm và nghiên cứu rất nhiều, tôi phát hiện ra rằng tôi đã tạo ra quá nhiều phiên bản của D3d11Device, trong trường hợp của tôi, tôi đã tạo ra 2 đến 3 thiết bị để Chụp, chuyển đổi màu và mã hóa phần cứng tương ứng. Trong khi đó, tôi chỉ có thể sử dụng lại một cá thể D3dDevice. Tuy nhiên, việc tạo nhiều phiên bản D3d11Device có thể hoạt động trên các máy cao cấp. Điều này không được ghi nhận ở bất cứ đâu. Tôi thậm chí không thể tìm ra manh mối cho các nguyên nhân gây ra lỗi "MEError". Nó không được đề cập đến.

Việc sử dụng lại cá thể D3D11Device đã giải quyết được vấn đề. Đăng giải pháp này vì nó có thể hữu ích cho những người phải đối mặt với vấn đề tương tự như của tôi.


Tôi không thấy trong bài viết của bạn có đề cập đến lỗi E_UNEXPECTED ...
mofo77

@ mofo77, Xin lỗi, đó là MEError = 1 ("Lỗi không xác định") như được đề cập trong bài đăng. Tôi mất trí rồi. Sửa câu trả lời của tôi. Cảm ơn đã chỉ ra.
Ram
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.