在您的情况下,实施SourceReader不是必需的,但您可以继续实施它,它会起作用。
相反,您也可以直接将通过桌面复制捕获的输入缓冲区提供给 SinkWriter。就像下面一样,
CComPtr<IMFAttributes> attribs;
CComPtr<IMFMediaSink> m_media_sink;
IMFSinkWriterPtr m_sink_writer;
MFCreateAttributes(&attribs, 0);
attribs->SetUINT32(MF_LOW_LATENCY, TRUE);
attribs->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE);
IMFMediaTypePtr mediaTypeOut = MediaTypeutput(fps, bit_rate);
MFCreateFMPEG4MediaSink(stream, mediaTypeOut, nullptr, &m_media_sink));
MFCreateSinkWriterFromMediaSink(m_media_sink, attribs, &m_sink_writer);
//Set input media type
mediaTypeIn->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32);
//Set output media type
mediaTypeOut->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264);
IMFSamplePtr sample;
MFCreateSample(&sample);
sample->AddBuffer(m_buffer); // m_buffer is source buffer in R8G8B8A8 format
sample->SetSampleTime(m_time_stamp);
sample->SetSampleDuration(m_frame_duration);
m_sink_writer->WriteSample(m_stream_index, sample);
这是一个基于 SinkWriter 的完美工作示例。它同时支持网络和文件接收器。它实际上通过 GDI 方法捕获桌面。DDA 几乎一样,使用 DDA 确实可以获得更好的性能。
我还在这里上传了一个实际上基于桌面复制的示例,并直接使用IMFTransform代替,并使用 Live555 将输出视频流式传输为 RTP 流。通过这种方法,我能够达到 100FPS。
如果您决定采用 SinkWriter 方法,则不必担心颜色转换部分,因为它由 SinkWriter 在后台负责。使用IMFTransform,您将不得不处理颜色转换部分,但您将对编码器进行细粒度控制。
这里有一些更多的参考链接供您参考。
- https://github.com/ashumeow/webrtc4all/blob/master/gotham/MFT_WebRTC4All/test/test_encoder.cc
- DXGI 桌面复制:编码帧以通过网络发送它们
- 在 ffplay 中获得绿屏:使用 Live555 通过 RTP 流将桌面(DirectX 表面)流式传输为 H264 视频
- 输入少量输入样本后,英特尔图形硬件 H264 MFT ProcessInput 调用失败,同样适用于 Nvidia 硬件 MFT
- 使用 DirectX11 像素着色器在 GPU 中从 DXGI_FORMAT_B8G8R8A8_UNORM 到 NV12 的颜色转换
- 英特尔 H264 硬件 MFT 不支持 GOP 设置
- 使用 Media Foundation 对通过桌面复制获得的 D3D 表面进行编码