当应用程序是视频源并通过网络流式传输视频时如何使用媒体基础?

How to use Media Foundation when application is video source and streams video via network?

我正准备用 C++ 编写一个模拟器。它是一个控制台应用程序,它...模拟东西并有一个 REST-ful 套接字 API 来填充 impacts/contributes 到模拟。为了查看模拟中发生的情况,我想出了生成反映模拟器状态的一系列图像(位图)的绝妙主意。然后将其简单地流式传输为电影,这样我就可以通过媒体播放器(例如 VLC 或 Windows 媒体播放器)观看我的模拟器模拟。或者将视频保存到文件(第二个选项)。或者两者兼而有之。

在 Windows 7 (x64) 上,Windows Media Foundation 看起来像是用于此的技术。只是我不想成为媒体基础专家,宁愿专注于我的模拟器。

它应该是这样工作的:

我现在觉得困难的是弄清楚如何最好地编排和 select 媒体基础中将进行编码的部分。

我想我必须实现自定义 IMFMediaSource COM object 并将其用作管道的起点。但是我没有找到如何从管道中获取编码的 jpeg 图像或一些 IMFMediaSink 视频流数据,以便我可以用它来提供我的网络层。

所以这里我的问题集需要媒体基础专家的帮助:

由于我在 COM 编程和其他基础知识方面有经验,我真正需要的只是一个快捷方式,所以我不必学习 trial-and-error 媒体基金会来了解如何实现这个用例或至少有信息可以帮助我找到一个好的起点。

提前致谢!

这里是应用程序如何访问它的草稿:

#include <cstdint>

struct SourceFormatDescriptor
{
    uint32_t width;
    uint32_t height;
    uint32_t colorDepth; // Bytes per pixel -> RGB (3 bytes per pixel) | RGBA (4 bytes per pixel)
};

struct IVideoStreamReceiver
{
    virtual void Starting() = 0;
    virtual void Ending() = 0;
    virtual uint32_t MaxChunkSize() = 0; // Somehow network protocol MTU related
    // Can/should be directly forwarded to network layer and/or saved to file.
    virtual void VideoChunk(size_t chunkSize, const uint8_t* chunk) = 0;
};

// Application object behind which all video rendering voodoo will be implemented.
class VideoRenderer
{
    // Is initialized once and fixed while the streaming is done.
    SourceFormatDescriptor m_sourceDescriptor;

public:
    VideoRenderer(const SourceFormatDescriptor& sourceDescriptor);

    void Start();
    void Stop();

    // Not sure who drives the renderer (Media foundation or external clock?)
    void MediaClockTick(); // dummy reminder function

    void AddReceiver(IVideoStreamReceiver* receiver);

    // Whenever a new frame is rendered it is passed to the video renderer.
    void NewFrame(const uint8_t * frameData, size_t frameSize);
};

我一直在使用 Windows Media Foundation 并试图掌握它有一段时间了,但我处于专家的另一端。根据我对 MF 的经验,我建议为您的位图找到一种不同的方法来处理视频流逻辑。虽然 MF 可以对 H264 进行位图编码(如果您要通过网络,您确实希望这样做),但它仅提供与流媒体网络协议的极小集成。据我所知,这仅限于允许基本 RTSP 服务器与 SourceReader 一起使用,但没有网络功能作为 SinkWriter 的输出,这正是您所需要的。因此,您必须按照您提到的方式自己动手,但是 RTP/RTSP 堆栈将比您想象的更重要。

可能适合您的一个选项是 ffmpeg。通过直接使用一个预构建的 exe 或通过使用项目中包含的库。看看这个SO question。诸如 ffmpeg 之类的外部库解决方案可能不如使用 MF 干净,但在您的情况下,它会花费您更少的精力。 ffmpeg 确实对包括 RTP 和 RTSP 在内的网络流式传输有更好的支持。