c++ - 媒体基金会 : Getting a MediaSink from a SinkWriter

标签 c++ ms-media-foundation

我正在尝试将 MP4 文件接收器添加到拓扑中。当我的 MediaSource 已经是 MP4 时,我使用 MFCreateMPEG4MediaSinkMF_MPEG4SINK_SPSPPS_PASSTHROUGH。当我的 MediaSource 不是 MP4(来自网络摄像头的原始 YUV)时,我想使用 MFCreateSinkWriterFromURL 这样我就不必弄清楚 MP4 header 和其他复杂的内容东西。

根据the MSDN Docs我应该能够使用 GetServiceForStream 来获取 MediaSink,因为输入类型与输出类型不同。但它始终返回 MF_E_UNSUPPORTED_SERVICE

如何从 MediaSinkWriter 中获取底层 MediaSink

或者,如何轻松地为任意拓扑创建 MP4 媒体接收器?

HRESULT CreateVideoFileSink(
    IMFStreamDescriptor *pSourceSD,     // Pointer to the stream descriptor.
    LPCWSTR pFilename,                  // Name of file to save to.
    IMFStreamSink **ppStream)           // Receives a pointer to the stream sink.
    HRESULT hr = S_OK;
    CComPtr<IMFAttributes> pAttr;
    CComPtr<IMFMediaTypeHandler> pHandler;
    CComPtr<IMFMediaType> pType;
    CComPtr<IMFMediaSink> pSink;
    CComPtr<IMFStreamSink> pStream;
    CComPtr<IMFSinkWriter> pSinkWriter;
    CComPtr<IMFByteStream> pByteStream;

    *ppStream = nullptr;

    // Get the media type handler for the stream.
    IFR(pSourceSD->GetMediaTypeHandler(&pHandler));

    // Get the major media type.
    GUID guidMajorType;
    IFR(pHandler->GetMajorType(&guidMajorType));

    IFR(MFCreateAttributes(&pAttr, 1));
    IFR(pAttr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE));

    // Create an output file 
    if (MFMediaType_Video == guidMajorType)
    {
        GUID guidSubType;
        IFR(pHandler->GetCurrentMediaType(&pType));
        IFR(pType->GetGUID(MF_MT_SUBTYPE, &guidSubType));

        if (MFVideoFormat_H264 == guidSubType)
        {
            // ... use MFCreateMPEG4MediaSink
        }
        else
        {
            IFR(MFCreateSinkWriterFromURL(pFilename, nullptr, pAttr, &pSinkWriter));
            DWORD streamIdx;
            IFR(pSinkWriter->AddStream(pType, &streamIdx));
            IFR(pSinkWriter->GetServiceForStream(MF_SINK_WRITER_MEDIASINK, GUID_NULL, IID_PPV_ARGS(&pSink)));
            IFR(pSink->GetStreamSinkByIndex(streamIdx, &pStream));
        }
    }
    else
    {
        // Don't use this stream
        IFR(E_FAIL)
    }

    // Return IMFStreamSink pointer to caller.
    *ppStream = pStream.Detach();

    return S_OK;
}

最佳答案

写完问题后就想出来了 - 当然。 SinkWriter没有 MediaSink直到您调用BeginWriting .

IFR(MFCreateSinkWriterFromURL(pFilename, nullptr, pAttr, &pSinkWriter));
DWORD streamIdx;
IFR(pSinkWriter->AddStream(pType, &streamIdx));
IFR(pSinkWriter->BeginWriting()); // <<----
IFR(pSinkWriter->GetServiceForStream(MF_SINK_WRITER_MEDIASINK, GUID_NULL, IID_PPV_ARGS(&pSink)));
IFR(pSink->GetStreamSinkByIndex(streamIdx, &pStream));

(确保在使用 SinkWriter 时不要让 StreamSink 被释放)

关于c++ - 媒体基金会 : Getting a MediaSink from a SinkWriter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49459148/

相关文章:

c++ - HANDLE 和 DCB 的 Linux 实现

c++ - 读取文件并将其存储在 unordered_map 中时出现问题

c++ - 将 IMFSample* 转换为 ID3D11ShaderResourceView*

c++ - UWP,媒体基础,选择特定的编码器

c++ - 从弧度转换为度数

c++ - 引脚二进制检测 : How to precisely identify a function name.

c++ - 数独空白 - C++

c++ - 用于 MKV 文件的开源 WinRT 库

c# - C# 媒体基础

c++ - 媒体基础 SinkWriter (MP4 FastStart)