当应用程序是视频源并通过网络流式传输视频时,如何使用Media Foundation?

时间:2015-03-14 23:52:19

标签: c++ video simulator ms-media-foundation

我即将在C ++中编写一个类似的模拟器。它是一个控制台应用程序,它...模拟东西,并有一个REST-ful套接字API来影响/有助于模拟。为了看看模拟中发生了什么,我有一个很棒的想法来生成一系列反映模拟器状态的图像(位图)。然后简单地将其作为电影流式传输,这样我就可以观看从媒体播放器模拟的模拟器,例如VLC或Windows媒体播放器。或者将视频保存到文件(第二个选项)。或两者兼而有之。

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

以下是它的工作方式:

  • 模拟器代码具有状态,可以呈现为位图(宽度,高度,......)。模拟器未实时运行(未计时)。它进行计算,并根据模拟器输入发生的情况,状态以非周期性方式变化。
  • 每当状态发生变化时,渲染一个位图并将其排队等待视频输出。由于视频(取决于视频流编码)期望某种恒定的帧速率,因此最后的图像应该被简单地重新发送,直到存在新的帧,从而创建视频。但他们似乎把帧持续时间视为常数。
  • Media Foundation似乎不包含现成的代码来实现我的应用程序的(基于UDP或TCP的RTP / RSTP)接口。所以我希望它能为我做一个从位图到jpeg帧的转换,并为我提供某种形式的媒体时钟。
    • 我想我弄清楚这些RTP等标题是如何工作的,并且可以自己轻松编程网络端。如果这种方法是最快的方法。

我现在觉得困难的是弄清楚如何最好地协调和选择将进行编码的Media Foundation部分。

我认为我必须实现一个自定义IMFMediaSource COM对象并将其用作管道的开头。但我没有找到如何从管道中获取编码的jpeg图像或一些IMFMediaSink视频流数据,因此我可以用它来提供我的网络层。

所以,我在媒体基金会专家的帮助下提出了一系列问题:

  • 我有什么捷径要做我的想法吗?我并不关注RTP / RTSP - 任何形式的视频格式都可以。只要我投入的工作量很少,我就可以使用标准播放器。
  • 有人可以为我创建一个简短的清单,我该怎么办?它可以是漂亮的鸟瞰。喜欢"创建实现接口的COM对象[list] - 使用Mediafoundation编解码器和诸如[name]来构建管道 - 在您的接收器对象中实现IMFMediaSink并获取类似......这样的数据......媒体时钟是提供者(我是否必须从后面为管道提供时钟,因为它是一个拉模型,或者是由会话中的某个时钟驱动的IMFMediaSink?)等等。"?
  • 如果我要使用h.264编码器 - 我可以恢复数据还是仅渲染到文件?我是否需要额外的协议标头才能通过网络套接字流式传输?

由于我在COM编程和其他基础知识方面有经验,我真正需要的只是一个快捷方式,所以我不需要与Media Foundation一起学习和反复试验,以了解如何实现这个用例或至少有信息帮助我找到了一个很好的起点。

提前致谢!

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

#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);
};

1 个答案:

答案 0 :(得分:1)

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

可能适合您的一个选项是ffmpeg。通过直接使用其中一个预先构建的exes或使用项目中包含的库。看一下这个SO question。诸如ffmpeg之类的外部库解决方案可能不如使用MF那样干净,但在您的情况下,它会减少您的工作量。 ffmpeg对网络流媒体有更好的支持,包括RTP和RTSP。