【问题标题】:How to duplicate IMFSample object如何复制 IMFSample 对象
【发布时间】:2016-07-13 14:42:46
【问题描述】:

我需要复制IMFSample 对象,以便拥有单独的独立对象。 Microsoft API 不提供复制IMFSample 视频帧的简便方法。

【问题讨论】:

    标签: c++ windows win-universal-app video-processing ms-media-foundation


    【解决方案1】:

    这是一个示例代码:

    #define MmfThrowIfError(hrVal) \
    { \
        HRESULT hrMmfTraceInternal = (hrVal); \
        if (FAILED(hrMmfTraceInternal)) \
        { \
            /* LOG_F(LS_ERROR)<<"MMF hr: 0x"<<std::hex<<hrMmfTraceInternal; */ \
            throw ref new ::Platform::Exception(hrMmfTraceInternal); \
        } \
    }
    
    MFComPtr<IMFMediaBuffer> DuplicateBuffer(const MFComPtr<IMFMediaBuffer>& srcBuf)
    {
        byte* srcByteBuffer = nullptr;
        DWORD srcBuffMaxLen = 0;
        DWORD srcBuffCurrLen = 0;
        MmfThrowIfError(srcBuf->Lock(&srcByteBuffer, &srcBuffMaxLen, &srcBuffCurrLen));
    
        MFComPtr<IMFMediaBuffer> destBuf = nullptr;
        MmfThrowIfError(MFCreateMemoryBuffer(srcBuffCurrLen, &destBuf));
    
        byte* destByteBuffer = nullptr;
        MmfThrowIfError(destBuf->Lock(&destByteBuffer, nullptr, nullptr));
        memcpy(destByteBuffer, srcByteBuffer, srcBuffCurrLen);
        MmfThrowIfError(destBuf->Unlock());
        MmfThrowIfError(srcBuf->Unlock());
    
        MmfThrowIfError(destBuf->SetCurrentLength(srcBuffCurrLen));
        return destBuf;
    }
    
    SampleComPtr DuplicateSample(const SampleComPtr& sample)
    {
        if (!sample)
            return nullptr;
    
        DWORD sampleFlags = 0;
        LONGLONG llVideoTimeStamp = 0;
        LONGLONG llSampleDuration = 0;
        MmfThrowIfError(sample->GetSampleFlags(&sampleFlags));
        MmfThrowIfError(sample->GetSampleTime(&llVideoTimeStamp));
        MmfThrowIfError(sample->GetSampleDuration(&llSampleDuration));
    
        SampleComPtr outSample;
        MFCreateSample(&outSample);
        MmfThrowIfError(outSample->SetSampleFlags(sampleFlags));
        MmfThrowIfError(outSample->SetSampleTime(llVideoTimeStamp));
        MmfThrowIfError(outSample->SetSampleDuration(llSampleDuration));
    
        DWORD bufferCount = 0;
        MmfThrowIfError(sample->GetBufferCount(&bufferCount));
    
        for (DWORD index = 0; index < bufferCount; ++index)
        {
            MFComPtr<IMFMediaBuffer> srcBuf = nullptr;
            MmfThrowIfError(sample->GetBufferByIndex(index, &srcBuf));
    
            MFComPtr<IMFMediaBuffer> reConstructedBuffer = DuplicateBuffer(srcBuf);
            srcBuf = nullptr;
            MmfThrowIfError(outSample->AddBuffer(reConstructedBuffer.Get()));
        }
    
        return outSample;
    }
    

    【讨论】:

    • 这适用于大多数情况,但不是准确的副本。副本总是一个简单的样本,而原始样本可能有 Direct3D 纹理等支持。
    • “不准确”是什么意思?丢失了哪些样本方面? (除了缓冲区大小减少到它们的实际(非最大)大小)。
    • “准确”是指精确复制,它复制了所有功能。我在上面举了一个例子。此外,这正是示例复制 API 不存在的原因:Media Foundation 根本无法生成精确的副本,因为通常示例是特定于实现的,即使遵循通用接口集。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-03
    • 1970-01-01
    • 2012-03-10
    • 2023-03-16
    • 2011-02-04
    • 2019-03-18
    相关资源
    最近更新 更多