এফএফপ্লেতে সবুজ স্ক্রিন পাওয়া: লাইভ 555 ব্যবহার করে আরটিপি স্ট্রিমের উপরে H264 ভিডিও হিসাবে স্ট্রিমিং ডেস্কটপ (ডাইরেক্টএক্স পৃষ্ঠ)


9

আমি উইন্ডোজ 10 তে লাইভ 555 এবং উইন্ডোজ মিডিয়া ফাউন্ডেশনের হার্ডওয়্যার এনকোডার ব্যবহার করে আরটিপি স্ট্রিমের মাধ্যমে এইচ 264 ভিডিও হিসাবে ডেস্কটপটি (এনভি 12 ফর্ম্যাটে ডাইরেক্টএক্স পৃষ্ঠের) স্ট্রিম করার চেষ্টা করছি এবং এটি ffplay (ffmpeg 4.2) দ্বারা রেন্ডার হওয়ার প্রত্যাশা করছি। তবে কেবল নীচের মতো সবুজ পর্দা পাওয়া,

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

আমি লাইভ 555 এর ফ্রেমডোসোর্স বাস্তবায়নের জন্য হার্ডওয়্যার এমএফটি ব্যবহার করে এবং ইনপুট উত্সকে ওয়েবক্যামের পরিবর্তে ডাইরেক্টএক্স পৃষ্ঠে পরিবর্তনের জন্য এমএফওয়েবক্যামটোরআরটিপি মিডিয়াফাউন্ডেশন-নমুনা এবং এনকোডিং ডাইরেক্টএক্স পৃষ্ঠকে উল্লেখ করেছি।

ডাইরেক্টএক্স পৃষ্ঠ থেকে ইনপুট নমুনাগুলি সরবরাহ করতে লাইভ 555 এর doGetNextFrame কলব্যাকের জন্য আমার প্রয়োগের একটি অংশ এখানে দেওয়া হয়েছে:

virtual void doGetNextFrame()
{
    if (!_isInitialised)
    {
        if (!initialise()) {
            printf("Video device initialisation failed, stopping.");
            return;
        }
        else {
            _isInitialised = true;
        }
    }

    //if (!isCurrentlyAwaitingData()) return;

    DWORD processOutputStatus = 0;
    HRESULT mftProcessOutput = S_OK;
    MFT_OUTPUT_STREAM_INFO StreamInfo;
    IMFMediaBuffer *pBuffer = NULL;
    IMFSample *mftOutSample = NULL;
    DWORD mftOutFlags;
    bool frameSent = false;
    bool bTimeout = false;

    // Create sample
    CComPtr<IMFSample> videoSample = NULL;

    // Create buffer
    CComPtr<IMFMediaBuffer> inputBuffer;
    // Get next event
    CComPtr<IMFMediaEvent> event;
    HRESULT hr = eventGen->GetEvent(0, &event);
    CHECK_HR(hr, "Failed to get next event");

    MediaEventType eventType;
    hr = event->GetType(&eventType);
    CHECK_HR(hr, "Failed to get event type");


    switch (eventType)
    {
    case METransformNeedInput:
        {
            hr = MFCreateDXGISurfaceBuffer(__uuidof(ID3D11Texture2D), surface, 0, FALSE, &inputBuffer);
            CHECK_HR(hr, "Failed to create IMFMediaBuffer");

            hr = MFCreateSample(&videoSample);
            CHECK_HR(hr, "Failed to create IMFSample");
            hr = videoSample->AddBuffer(inputBuffer);
            CHECK_HR(hr, "Failed to add buffer to IMFSample");

            if (videoSample)
            {
                _frameCount++;

                CHECK_HR(videoSample->SetSampleTime(mTimeStamp), "Error setting the video sample time.\n");
                CHECK_HR(videoSample->SetSampleDuration(VIDEO_FRAME_DURATION), "Error getting video sample duration.\n");

                // Pass the video sample to the H.264 transform.

                hr = _pTransform->ProcessInput(inputStreamID, videoSample, 0);
                CHECK_HR(hr, "The resampler H264 ProcessInput call failed.\n");

                mTimeStamp += VIDEO_FRAME_DURATION;
            }
        }

        break;

    case METransformHaveOutput:

        {
            CHECK_HR(_pTransform->GetOutputStatus(&mftOutFlags), "H264 MFT GetOutputStatus failed.\n");

            if (mftOutFlags == MFT_OUTPUT_STATUS_SAMPLE_READY)
            {
                MFT_OUTPUT_DATA_BUFFER _outputDataBuffer;
                memset(&_outputDataBuffer, 0, sizeof _outputDataBuffer);
                _outputDataBuffer.dwStreamID = outputStreamID;
                _outputDataBuffer.dwStatus = 0;
                _outputDataBuffer.pEvents = NULL;
                _outputDataBuffer.pSample = nullptr;

                mftProcessOutput = _pTransform->ProcessOutput(0, 1, &_outputDataBuffer, &processOutputStatus);

                if (mftProcessOutput != MF_E_TRANSFORM_NEED_MORE_INPUT)
                {
                    if (_outputDataBuffer.pSample) {

                        //CHECK_HR(_outputDataBuffer.pSample->SetSampleTime(mTimeStamp), "Error setting MFT sample time.\n");
                        //CHECK_HR(_outputDataBuffer.pSample->SetSampleDuration(VIDEO_FRAME_DURATION), "Error setting MFT sample duration.\n");

                        IMFMediaBuffer *buf = NULL;
                        DWORD bufLength;
                        CHECK_HR(_outputDataBuffer.pSample->ConvertToContiguousBuffer(&buf), "ConvertToContiguousBuffer failed.\n");
                        CHECK_HR(buf->GetCurrentLength(&bufLength), "Get buffer length failed.\n");
                        BYTE * rawBuffer = NULL;

                        fFrameSize = bufLength;
                        fDurationInMicroseconds = 0;
                        gettimeofday(&fPresentationTime, NULL);

                        buf->Lock(&rawBuffer, NULL, NULL);
                        memmove(fTo, rawBuffer, fFrameSize);

                        FramedSource::afterGetting(this);

                        buf->Unlock();
                        SafeRelease(&buf);

                        frameSent = true;
                        _lastSendAt = GetTickCount();

                        _outputDataBuffer.pSample->Release();
                    }

                    if (_outputDataBuffer.pEvents)
                        _outputDataBuffer.pEvents->Release();
                }

                //SafeRelease(&pBuffer);
                //SafeRelease(&mftOutSample);

                break;
            }
        }

        break;
    }

    if (!frameSent)
    {
        envir().taskScheduler().triggerEvent(eventTriggerId, this);
    }

    return;

done:

    printf("MediaFoundationH264LiveSource doGetNextFrame failed.\n");
    envir().taskScheduler().triggerEvent(eventTriggerId, this);
}

প্রাথমিক পদ্ধতি:

bool initialise()
{
    HRESULT hr;
    D3D11_TEXTURE2D_DESC desc = { 0 };

    HDESK CurrentDesktop = nullptr;
    CurrentDesktop = OpenInputDesktop(0, FALSE, GENERIC_ALL);
    if (!CurrentDesktop)
    {
        // We do not have access to the desktop so request a retry
        return false;
    }

    // Attach desktop to this thread
    bool DesktopAttached = SetThreadDesktop(CurrentDesktop) != 0;
    CloseDesktop(CurrentDesktop);
    CurrentDesktop = nullptr;
    if (!DesktopAttached)
    {
        printf("SetThreadDesktop failed\n");
    }

    UINT32 activateCount = 0;

    // h264 output
    MFT_REGISTER_TYPE_INFO info = { MFMediaType_Video, MFVideoFormat_H264 };

    UINT32 flags =
        MFT_ENUM_FLAG_HARDWARE |
        MFT_ENUM_FLAG_SORTANDFILTER;

    // ------------------------------------------------------------------------
    // Initialize D3D11
    // ------------------------------------------------------------------------

    // Driver types supported
    D3D_DRIVER_TYPE DriverTypes[] =
    {
        D3D_DRIVER_TYPE_HARDWARE,
        D3D_DRIVER_TYPE_WARP,
        D3D_DRIVER_TYPE_REFERENCE,
    };
    UINT NumDriverTypes = ARRAYSIZE(DriverTypes);

    // Feature levels supported
    D3D_FEATURE_LEVEL FeatureLevels[] =
    {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_9_1
    };
    UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels);

    D3D_FEATURE_LEVEL FeatureLevel;

    // Create device
    for (UINT DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex)
    {
        hr = D3D11CreateDevice(nullptr, DriverTypes[DriverTypeIndex], nullptr,
            D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
            FeatureLevels, NumFeatureLevels, D3D11_SDK_VERSION, &device, &FeatureLevel, &context);
        if (SUCCEEDED(hr))
        {
            // Device creation success, no need to loop anymore
            break;
        }
    }

    CHECK_HR(hr, "Failed to create device");

    // Create device manager
    UINT resetToken;
    hr = MFCreateDXGIDeviceManager(&resetToken, &deviceManager);
    CHECK_HR(hr, "Failed to create DXGIDeviceManager");

    hr = deviceManager->ResetDevice(device, resetToken);
    CHECK_HR(hr, "Failed to assign D3D device to device manager");


    // ------------------------------------------------------------------------
    // Create surface
    // ------------------------------------------------------------------------
    desc.Format = DXGI_FORMAT_NV12;
    desc.Width = surfaceWidth;
    desc.Height = surfaceHeight;
    desc.MipLevels = 1;
    desc.ArraySize = 1;
    desc.SampleDesc.Count = 1;

    hr = device->CreateTexture2D(&desc, NULL, &surface);
    CHECK_HR(hr, "Could not create surface");

    hr = MFTEnumEx(
        MFT_CATEGORY_VIDEO_ENCODER,
        flags,
        NULL,
        &info,
        &activateRaw,
        &activateCount
    );
    CHECK_HR(hr, "Failed to enumerate MFTs");

    CHECK(activateCount, "No MFTs found");

    // Choose the first available encoder
    activate = activateRaw[0];

    for (UINT32 i = 0; i < activateCount; i++)
        activateRaw[i]->Release();

    // Activate
    hr = activate->ActivateObject(IID_PPV_ARGS(&_pTransform));
    CHECK_HR(hr, "Failed to activate MFT");

    // Get attributes
    hr = _pTransform->GetAttributes(&attributes);
    CHECK_HR(hr, "Failed to get MFT attributes");

    // Unlock the transform for async use and get event generator
    hr = attributes->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK, TRUE);
    CHECK_HR(hr, "Failed to unlock MFT");

    eventGen = _pTransform;
    CHECK(eventGen, "Failed to QI for event generator");

    // Get stream IDs (expect 1 input and 1 output stream)
    hr = _pTransform->GetStreamIDs(1, &inputStreamID, 1, &outputStreamID);
    if (hr == E_NOTIMPL)
    {
        inputStreamID = 0;
        outputStreamID = 0;
        hr = S_OK;
    }
    CHECK_HR(hr, "Failed to get stream IDs");

     // ------------------------------------------------------------------------
    // Configure hardware encoder MFT
   // ------------------------------------------------------------------------
    CHECK_HR(_pTransform->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, reinterpret_cast<ULONG_PTR>(deviceManager.p)), "Failed to set device manager.\n");

    // Set low latency hint
    hr = attributes->SetUINT32(MF_LOW_LATENCY, TRUE);
    CHECK_HR(hr, "Failed to set MF_LOW_LATENCY");

    hr = MFCreateMediaType(&outputType);
    CHECK_HR(hr, "Failed to create media type");

    hr = outputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
    CHECK_HR(hr, "Failed to set MF_MT_MAJOR_TYPE on H264 output media type");

    hr = outputType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264);
    CHECK_HR(hr, "Failed to set MF_MT_SUBTYPE on H264 output media type");

    hr = outputType->SetUINT32(MF_MT_AVG_BITRATE, TARGET_AVERAGE_BIT_RATE);
    CHECK_HR(hr, "Failed to set average bit rate on H264 output media type");

    hr = MFSetAttributeSize(outputType, MF_MT_FRAME_SIZE, desc.Width, desc.Height);
    CHECK_HR(hr, "Failed to set frame size on H264 MFT out type");

    hr = MFSetAttributeRatio(outputType, MF_MT_FRAME_RATE, TARGET_FRAME_RATE, 1);
    CHECK_HR(hr, "Failed to set frame rate on H264 MFT out type");

    hr = outputType->SetUINT32(MF_MT_INTERLACE_MODE, 2);
    CHECK_HR(hr, "Failed to set MF_MT_INTERLACE_MODE on H.264 encoder MFT");

    hr = outputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
    CHECK_HR(hr, "Failed to set MF_MT_ALL_SAMPLES_INDEPENDENT on H.264 encoder MFT");

    hr = _pTransform->SetOutputType(outputStreamID, outputType, 0);
    CHECK_HR(hr, "Failed to set output media type on H.264 encoder MFT");

    hr = MFCreateMediaType(&inputType);
    CHECK_HR(hr, "Failed to create media type");

    for (DWORD i = 0;; i++)
    {
        inputType = nullptr;
        hr = _pTransform->GetInputAvailableType(inputStreamID, i, &inputType);
        CHECK_HR(hr, "Failed to get input type");

        hr = inputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
        CHECK_HR(hr, "Failed to set MF_MT_MAJOR_TYPE on H264 MFT input type");

        hr = inputType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12);
        CHECK_HR(hr, "Failed to set MF_MT_SUBTYPE on H264 MFT input type");

        hr = MFSetAttributeSize(inputType, MF_MT_FRAME_SIZE, desc.Width, desc.Height);
        CHECK_HR(hr, "Failed to set MF_MT_FRAME_SIZE on H264 MFT input type");

        hr = MFSetAttributeRatio(inputType, MF_MT_FRAME_RATE, TARGET_FRAME_RATE, 1);
        CHECK_HR(hr, "Failed to set MF_MT_FRAME_RATE on H264 MFT input type");

        hr = _pTransform->SetInputType(inputStreamID, inputType, 0);
        CHECK_HR(hr, "Failed to set input type");

        break;
    }

    CheckHardwareSupport();

    CHECK_HR(_pTransform->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, NULL), "Failed to process FLUSH command on H.264 MFT.\n");
    CHECK_HR(_pTransform->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, NULL), "Failed to process BEGIN_STREAMING command on H.264 MFT.\n");
    CHECK_HR(_pTransform->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, NULL), "Failed to process START_OF_STREAM command on H.264 MFT.\n");

    return true;

done:

    printf("MediaFoundationH264LiveSource initialisation failed.\n");
    return false;
}


    HRESULT CheckHardwareSupport()
    {
        IMFAttributes *attributes;
        HRESULT hr = _pTransform->GetAttributes(&attributes);
        UINT32 dxva = 0;

        if (SUCCEEDED(hr))
        {
            hr = attributes->GetUINT32(MF_SA_D3D11_AWARE, &dxva);
        }

        if (SUCCEEDED(hr))
        {
            hr = attributes->SetUINT32(CODECAPI_AVDecVideoAcceleration_H264, TRUE);
        }

#if defined(CODECAPI_AVLowLatencyMode) // Win8 only

        hr = _pTransform->QueryInterface(IID_PPV_ARGS(&mpCodecAPI));

        if (SUCCEEDED(hr))
        {
            VARIANT var = { 0 };

            // FIXME: encoder only
            var.vt = VT_UI4;
            var.ulVal = 0;

            hr = mpCodecAPI->SetValue(&CODECAPI_AVEncMPVDefaultBPictureCount, &var);

            var.vt = VT_BOOL;
            var.boolVal = VARIANT_TRUE;
            hr = mpCodecAPI->SetValue(&CODECAPI_AVEncCommonLowLatency, &var);
            hr = mpCodecAPI->SetValue(&CODECAPI_AVEncCommonRealTime, &var);

            hr = attributes->SetUINT32(CODECAPI_AVLowLatencyMode, TRUE);

            if (SUCCEEDED(hr))
            {
                var.vt = VT_UI4;
                var.ulVal = eAVEncCommonRateControlMode_Quality;
                hr = mpCodecAPI->SetValue(&CODECAPI_AVEncCommonRateControlMode, &var);

                // This property controls the quality level when the encoder is not using a constrained bit rate. The AVEncCommonRateControlMode property determines whether the bit rate is constrained.
                VARIANT quality;
                InitVariantFromUInt32(50, &quality);
                hr = mpCodecAPI->SetValue(&CODECAPI_AVEncCommonQuality, &quality);
            }
        }
#endif

        return hr;
    }

ffplay কমান্ড:

ffplay -protocol_whitelist file,udp,rtp -i test.sdp -x 800 -y 600 -profile:v baseline

আভ্যন্তরীন উৎপাদন:

v=0
o=- 0 0 IN IP4 127.0.0.1
s=No Name
t=0 0
c=IN IP4 127.0.0.1
m=video 1234 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1

আমি কী অনুপস্থিত তা আমি জানি না, আমি প্রায় এক সপ্তাহ ধরে কোনও অগ্রগতি ছাড়াই এটি ঠিক করার চেষ্টা করে যাচ্ছিলাম এবং প্রায় যা কিছু সম্ভব তার চেষ্টা করেছি। এছাড়াও, ভিডিও হিসাবে ডাইরেক্টএক্স পৃষ্ঠের এনকোড করার জন্য অনলাইন সংস্থানগুলি খুব সীমাবদ্ধ।

কোন সাহায্য প্রশংসা করা হবে।


1
আমি মনে করি যে আপনি METransforNeedInput এর পরে doGetNextFrame আবার কল করার জন্য ভুলভাবে প্রত্যাশা করছেন। আপনি কোনও বৈধ প্রক্রিয়াআউটপুট কল না পাওয়া পর্যন্ত এটির ভিতরে লুপ করা উচিত।
ভুভিার্ট

এইচআর = ইভেন্ট-> গেটটাইপ (& ইভেন্ট টাইপ); স্যুইচ (ইভেন্টটি টাইপ) {....} যদি (! ফ্রেমসেন্ট) {এনভিরি ()। টাস্ক শিডুলার ()। ট্রিগারইভেন্ট (ইভেন্টটি ট্রিগার আইড, এটি); We উপরের 2 টি ব্লক প্রসেসইনপুট কল করার ক্ষেত্রে যত্ন সহকারে নেয় যতক্ষণ না আমরা এনকোডার থেকে আউটপুট না পাই। আমি একই যাচাই করেছি। @ ভুভিার্ট
রাম

ফ্রেমসেন্ট সত্য হলে কী হয়? আপনি কি এই ক্ষেত্রে একটি নতুন ঘটনা ট্রিগার? তার পরে আপনার "রিটার্ন" বিবৃতি রয়েছে।
ভুভিার্ট

@ ভুভিার্ট এটিকে স্বয়ংক্রিয়ভাবে একটি লুপের অন্তর্নিহিত লাইভ 555 লাইব্রেরি দ্বারা কল করা হয়। "প্রক্রিয়া ইনপুট" এবং "প্রক্রিয়াআউটপুট" বিকল্প হিসাবে সুইচ বিবৃতিতে ইভেন্টের উপর ভিত্তি করে ডাকা হয়। আমি প্রসেসআউট থেকে একটি অবিচ্ছিন্ন স্ট্রিম পাচ্ছি, তবে কেবল এটি দেখতে সক্ষম হবেন না। আমি নিশ্চিত যে আমি নমুনা সময় এবং সময়কাল সঠিকভাবে সেট করছি।
রাম

1
আপনি প্রসেসআউটপুট থেকে এমএফ_পিআলআরআরএসএফআরএমসিপিআরএম_সিএইচএনজি পেয়েছেন এবং তদনুসারে হ্যান্ডেল ফর্ম্যাট পরিবর্তনটি পরীক্ষা করতে পারেন।
ভুভিার্ট

উত্তর:


6

এটা মনে হয় চেয়ে কঠিন।

আইএমএফটি ট্রান্সফর্ম ইন্টারফেসকে সরাসরি কল করে আপনি যদি এনকোডারটি যেমন করছেন তেমন ব্যবহার করতে চান , আপনাকে আরজিবি ফ্রেমগুলিকে এনভি 12 এ রূপান্তর করতে হবে। আপনি যদি ভাল পারফরম্যান্স চান, আপনার এটি জিপিইউতে করা উচিত। পিক্সেল শেডারগুলির সাথে কাজ করা সম্ভব, 2 ফ্রেম রেন্ডার করুন, পূর্ণ আকার এক DXGI_FORMAT_R8_UNORM তে উজ্জ্বলতার সাথে লক্ষ্য রেন্ডার করুন, DXGI_FORMAT_R8G8_UNORM টার্গেটে রঙের সাথে অর্ধেক আকার দিন এবং এনভি 12 মান উত্পাদন করতে দুটি পিক্সেল শেডার লিখুন। উভয় রেন্ডার লক্ষ্যমাত্রা একই এনভি 12 টেক্সচারের 2 টি প্লেনগুলিতে রেন্ডার করতে পারে তবে উইন্ডোজ 8 এর পর থেকেই।

অন্যান্য পদ্ধতিটি হ'ল সিঙ্ক রাইটার ব্যবহার । এটি একই সাথে একাধিক এমএফটি হোস্ট করতে পারে যাতে আপনি ভিআরএমে আরজিবি টেক্সচার সরবরাহ করতে পারেন, ডুব লেখক প্রথমে তাদেরকে একটি এমএফটি দিয়ে এনভি 12 এ রূপান্তরিত করবেন (এটি সম্ভবত এনকোডারের মতো জিপিইউ ড্রাইভার দ্বারা প্রয়োগ করা মালিকানাধীন হার্ডওয়্যার হতে পারে), এনকোডার এমএফটি পাস। এমপি 4 ফাইলে এনকোড করা তুলনামূলকভাবে সহজ, লেখক তৈরি করতে এমএফসিআরটিসিনকিট্রাইটারফ্রوم URL এপিআই ব্যবহার করুন । ডুব লেখকের বাইরে কাঁচা নমুনা পাওয়া খুব বেশি শক্ত, তবে আপনাকে নিজের ভিডিও স্ট্রিমের জন্য একটি কাস্টম মিডিয়া সিঙ্ক, কাস্টম স্ট্রিম সিঙ্কটি প্রয়োগ করতে হবে এবং লেখক তৈরি করতে এমএফসিআরটসিঙ্ক রাইটারফ্রোমমিডিয়াসিংকে কল করতে হবে।

আরো আছে.

এনকোডিং পদ্ধতি নির্বিশেষে, আপনি ফ্রেম টেক্সচার পুনরায় ব্যবহার করতে পারবেন না। প্রতিটি ফ্রেম আপনি ডিডি থেকে পাবেন, আপনার একটি নতুন টেক্সচার তৈরি করা উচিত এবং এটি এমএফ-এ প্রেরণ করা উচিত।

ভিডিও এনকোডাররা ধ্রুব ফ্রেমের হার আশা করে। ডিডি আপনাকে তা দেয় না, এটি আপনাকে প্রতিটি সময় স্ক্রিনে কিছু পরিবর্তন করার সাথে সাথে একটি ফ্রেম দেয়। আপনার যদি গেমিং মনিটর থাকে তবে 144 টি এফপিএস হতে পারে, কেবলমাত্র পরিবর্তন ঘেমে যাওয়া কার্সার হলে 2 টি এফপিএস হতে পারে। আদর্শভাবে, আপনার ভিডিও মিডিয়া ধরণে নির্দিষ্ট করে আপনার ধ্রুবক ফ্রেমের হারে এমএফ-এর কাছে ফ্রেমগুলি জমা দেওয়া উচিত।

আপনি যদি নেটওয়ার্কে স্ট্রিম করতে চান তবে প্রায়শই আপনাকে প্যারামিটার সেট সরবরাহ করতে হবে না। আপনি যদি ইন্টেল থেকে কোনও মন্তব্য না করে ভাঙা ইন্টেল হার্ডওয়্যার এইচ 265 এনকোডার ব্যবহার না করেন , এমএফএমডিএমএফএমডিএমটাইপআইডিএফটাইম হ্যান্ডলার ইন্টারফেসে সেটক্রেনারমিডিয়া টাইপ কল করে মিডিয়া প্রকারের এমফ_এমT_MPEG_SEQUENCE_HEADER অ্যাট্রিবিউটে আপনাকে সেই ডেটা দেয় । আপনি বিজ্ঞপ্তি পেতে যে ইন্টারফেস বাস্তবায়ন করতে পারেন। আপনি এনকোডিং শুরু করার পরে কেবলমাত্র সেই ডেটা পাবেন। এর আপনি একটি বেসিনে লেখক ব্যবহার করেন, এর জন্য যে IMFTransformপদ্ধতি আরও সহজ, আপনি পাওয়া উচিত MF_E_TRANSFORM_STREAM_CHANGEকোড থেকে ProcessOutputপদ্ধতি, তারপর কল GetOutputAvailableTypeযে জাদু ফোঁটা সঙ্গে আপডেট মিডিয়া টাইপ জন্য।


আপনার অর্থ ডাইরেক্টএক্স (ডেস্কটপ সদৃশ) NV12 ফর্ম্যাটে ফ্রেম সরবরাহ করে না এমনকি যখন ডিভাইসটি D3D11_CREATE_DEVICE_VIDEO_SUPPORT এবং পৃষ্ঠ বর্ণনাকারীর সাথে DXGI_FORMAT_NV12 তে রূপান্তরিত হয় এবং MFT_MESSAGE_SET_D3D_MANAGER রূপান্তরিত করে? আমিও ভেবেছিলাম যে আমাদের আরজিবি বাফারকে স্পষ্টভাবে NV12 বা কোনও সমর্থিত ইনপুট ফর্ম্যাট (বেশিরভাগ YUV রূপগুলি) এ রূপান্তর করতে হবে বা একটি সিনক রাইটার ব্যবহার করতে হবে। কিন্তু, এই ব্যক্তিটি কোনও একরকম আমার পন্থায় নিজেকে অর্জন করতে সক্ষম হয়েছিল। stackoverflow.com/questions/43432670/…
রাম


1
@ র্যাম ডেস্কটপ সদৃশ সর্বদা DXGI_FORMAT_B8G8R8A8_UNORMবিন্যাসে আরজিবি ফ্রেম সরবরাহ করে। এইচ 264 এবং এইচ 265 এনকোডার এমএফটিগুলি কেবল এনভি 12 এবং অন্যদের দম্পতিকে সমর্থন করে, সমান অদ্ভুত। কাউকে ধর্মান্তর করতে হবে। আপনি ডেস্কটপ সদৃশ ব্যবহার; আপনি ইতিমধ্যে এটি দিয়ে উইন্ডোজ 7 সমর্থন করতে পারবেন না। একটি ডোবা লেখক ব্যবহার করুন। আমি নিশ্চিত যে এই এনভিডিয়া / ইন্টেলের হার্ডওয়্যার এমএফটিগুলি আরজিবিকে এনভি 12 এ রূপান্তর করতে পিক্সেল শেডার এএলইউগুলির তুলনায় আরও শক্তিশালী, তারা সম্ভবত হার্ডওয়ারে খাঁটি প্রয়োগ করেছে implemented
শীঘ্রই

তুমি ঠিক. রঙ রূপান্তর অবশ্যই স্পষ্টভাবে করা উচিত। github.com/GPUOpen- লাইব্রেরিএন্ডএসডিকিএস / এএমএফ / প্রচ্ছদ /92 । আমি সেই দিকে এগিয়ে যাচ্ছি।
রাম

1
@ র্যাম এটি কাজ করা উচিত, আমি আগে এটি করেছি। কোনও আপডেট নেই বলে ডিডি যখন আপনাকে নতুন ফ্রেম দিতে অস্বীকৃতি জানায়, আপনি আবার এনকোডারটিতে একই টেক্সচার জমা দিয়ে প্রচুর ভিআরএএম সংরক্ষণ করতে পারবেন। কেবল তখনই নতুন টেক্সচার তৈরি করুন যখন ডিডি-তে আপনার জন্য নতুন ফ্রেম তৈরি করা হবে। তবে আপনাকে কখন ফ্রেম জমা দিতে হবে এবং কতক্ষণ অপেক্ষা করতে হবে তা সনাক্ত করার কোডটি তুচ্ছ নয়। আমি সময়টি পরিমাপ করতে কোয়েরি পারফরম্যান্স কাউন্টার ব্যবহার করেছি এবং আমার ক্যাপচার হওয়া উচিত, বা আমার ঘুমানো উচিত তা খুঁজে পাওয়ার জন্য গত কয়েক ফ্রেমের উপরে এক ধরণের রোলিং গড়। বিটিডাব্লু, ঘুমের সঠিক উপায় হ'ল আইডিএক্সজিআইআউটপুট :: ওয়েটফরভিভিঙ্ক পদ্ধতি।
তাড়াতাড়ি

1

যেহেতু ffplayস্ট্রিম প্যারামিটার সম্পর্কে অভিযোগ করা হচ্ছে, তাই আমি ধরে নেব এটি এসপিএস / পিপিএস তুলতে পারে না। আপনি এগুলিকে আপনার হার্ডকোডযুক্ত এসডিপিতে সেট করেননি - আরএফসি -3984 দেখুন এবং সন্ধান করুন sprop-parameter-sets। আরএফসির একটি উদাহরণ:

মি = ভিডিও
49170 আরটিপি / এভিপি 98 এ = আরটিপিএম্যাপ: 98 এইচ
264/90000 এ = এফএমটিপি: 98 প্রোফাইল-স্তর-আইডি = 42A01E; স্প্রোপ-প্যারামিটার-সেট = জেড 0 আইএসিপিজেডটিবিওয়াই, এএমজিজি ==

আমি দৃ strongly়ভাবে ধরে নিয়েছি ffplayএসডিপিতে এগুলি প্রত্যাশা করছি। মিডিয়া ফাউন্ডেশন এনকোডার থেকে কীভাবে এসপিএস / পিপিএস পাবেন তা আমি হৃদয় দিয়ে মনে করি না, তবে হয় নমুনা পেওলডে রয়েছে এবং সঠিক এনএল ইউনিট বা গুগল কীভাবে অতিরিক্ত ডেটা বের করতে হবে তা খুঁজে বের করে আপনার এগুলি বের করতে হবে এনকোডার - প্রথম হিটটি আমি আশাব্যঞ্জক দেখলাম।


এটি একটি বৈধ পয়েন্ট। আমারও এসপিএস / পিপিএস-তে সন্দেহ আছে। আমি যদিও এটি যাচাই করতে এখনও। আমাকে এমএসডিএন থ্রেডে পরিচালিত করার জন্য ধন্যবাদ যা আমাকে কিছুটা আশা দেয়।
রাম

@ র্যাম একটি ভাল চঞ্চ আছে যে এসপিএস / পিপিএস নমুনা পেওলোডে রয়েছে, তাই আমি প্রথমে এটি পরীক্ষা করে দেখি।
রুডল্ফস বুন্ডুলিস

হ্যাঁ, আমি এটা বুঝতে পারি। আমি যখন এমপিইজি 4 মিডিয়াসিংকের মাধ্যমে কোনও ফাইলে নমুনা লেখার চেষ্টা করেছি তখন মিডিয়া ফাউন্ডেশন এনকোডারদের থেকে সরাসরি এসপিএস / পিপিএস পুনরুদ্ধার এবং পার্স করার কিছু জ্ঞান পেয়েছি। আমি এই দিকে এগিয়ে যেতে হবে।
রাম

1

শীঘ্রই আপনাকে আপনার সমস্যা সমাধানের জন্য প্রয়োজনীয় সমস্ত জিনিস দেয়।

আপনার প্রথমে যে কাজটি করা দরকার তা হ'ল DXGI_FORMAT_B8G8R8A8_UNORM এবং এমএফভিডিও ফর্ম্যাট_এনভি 12 এর মধ্যে ফর্ম্যাট রূপান্তর:

ফর্ম্যাট রূপান্তর

ফর্ম্যাট রূপান্তর তথ্য

আমি মনে করি ফর্ম্যাট রূপান্তর করতে শেডার ব্যবহার করা ভাল, কারণ সমস্ত টেক্সচার জিপিইউতে থাকবে (পারফরম্যান্সের জন্য আরও ভাল)।

এটি আপনার করা প্রথম পদক্ষেপ। আপনার প্রোগ্রামটি উন্নত করার জন্য আপনার কাছে অন্যরা থাকবে।


1
2x4 ইমেজটি এনভি 12-তে আপনার 12 টি নয়: 8 টি উজ্জ্বলতার মানগুলিতে 12 বাইট নেয়, তবে রঙের চিত্রটি দ্বিগুণ ছোট, 1x2 পিক্সেল, তাই 2x4 চিত্রের রঙ তথ্যের জন্য মোট 4 বাইট, ইউ এর জন্য 2 বাইট এবং
ভি.এর

হ্যাঁ আপনি ঠিক বলেছেন, আমি এনভি 12 ফর্ম্যাটটির ডাউনস্যাম্পলিংটিকে 4.2.0 এ বাদ দিয়েছি। আমি আরও মানানসই চিত্রটি তৈরি করার চেষ্টা করব।
mofo77
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.