当应用程序是视频源并通过网络流式传输视频时如何使用媒体基础?
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 看起来像是用于此的技术。只是我不想成为媒体基础专家,宁愿专注于我的模拟器。
它应该是这样工作的:
- 模拟器代码有状态,可以呈现为位图(宽度、高度...)。模拟器不是 real-time 中的 运行(未计时)。它进行计算,并根据模拟器输入发生的情况,状态以 non-periodic 方式变化。
- 每当状态发生变化时,渲染位图并queue 将其用于视频输出。由于视频(取决于视频流编码)需要某种恒定的帧速率,因此最后一张图像应简单地 re-transmitted 直到有新帧,从而创建视频。但是他们似乎把 frame-duration 当作一个常数来对待。
- 媒体基础似乎不包含 ready-made 代码来实现(基于 UDP 或 TCP RTP/RSTP)我的应用程序的接口。所以我希望它可以为我完成从位图到 jpeg 帧的转换,并为我提供某种形式的媒体时钟。
- 我想我弄清楚了那些 RTP 等 headers 是如何工作的,并且可以自己轻松地对网络端进行编程。如果该方法是最快的方法。
我现在觉得困难的是弄清楚如何最好地编排和 select 媒体基础中将进行编码的部分。
我想我必须实现自定义 IMFMediaSource
COM object 并将其用作管道的起点。但是我没有找到如何从管道中获取编码的 jpeg 图像或一些 IMFMediaSink
视频流数据,以便我可以用它来提供我的网络层。
所以这里我的问题集需要媒体基础专家的帮助:
- 有什么捷径可以让我按照自己的想法去做吗?我不关注 RTP/RTSP - 任何形式的视频格式都可以。只要我投入的工作量是最小的,我就可以使用标准播放器。
- 有人可以为我创建一个简短的清单吗?可以很漂亮bird-view。喜欢 "Create COM object which implements interfaces [list] - Use Mediafoundation codecs and whatnot [names] to build the pipeline - Implement IMFMediaSink in your sink object and get the data like...this ... The media clock is provided by (do I have to clock the pipeline from the back as it is a pull model or is the IMFMediaSink driven by some clock from within the session?) etc."?
- 如果我使用 h.264 编码器 - 我可以取回数据还是只渲染到文件?我是否需要额外的协议 headers 才能通过网络套接字进行流式传输?
由于我在 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 在内的网络流式传输有更好的支持。
我正准备用 C++ 编写一个模拟器。它是一个控制台应用程序,它...模拟东西并有一个 REST-ful 套接字 API 来填充 impacts/contributes 到模拟。为了查看模拟中发生的情况,我想出了生成反映模拟器状态的一系列图像(位图)的绝妙主意。然后将其简单地流式传输为电影,这样我就可以通过媒体播放器(例如 VLC 或 Windows 媒体播放器)观看我的模拟器模拟。或者将视频保存到文件(第二个选项)。或者两者兼而有之。
在 Windows 7 (x64) 上,Windows Media Foundation 看起来像是用于此的技术。只是我不想成为媒体基础专家,宁愿专注于我的模拟器。
它应该是这样工作的:
- 模拟器代码有状态,可以呈现为位图(宽度、高度...)。模拟器不是 real-time 中的 运行(未计时)。它进行计算,并根据模拟器输入发生的情况,状态以 non-periodic 方式变化。
- 每当状态发生变化时,渲染位图并queue 将其用于视频输出。由于视频(取决于视频流编码)需要某种恒定的帧速率,因此最后一张图像应简单地 re-transmitted 直到有新帧,从而创建视频。但是他们似乎把 frame-duration 当作一个常数来对待。
- 媒体基础似乎不包含 ready-made 代码来实现(基于 UDP 或 TCP RTP/RSTP)我的应用程序的接口。所以我希望它可以为我完成从位图到 jpeg 帧的转换,并为我提供某种形式的媒体时钟。
- 我想我弄清楚了那些 RTP 等 headers 是如何工作的,并且可以自己轻松地对网络端进行编程。如果该方法是最快的方法。
我现在觉得困难的是弄清楚如何最好地编排和 select 媒体基础中将进行编码的部分。
我想我必须实现自定义 IMFMediaSource
COM object 并将其用作管道的起点。但是我没有找到如何从管道中获取编码的 jpeg 图像或一些 IMFMediaSink
视频流数据,以便我可以用它来提供我的网络层。
所以这里我的问题集需要媒体基础专家的帮助:
- 有什么捷径可以让我按照自己的想法去做吗?我不关注 RTP/RTSP - 任何形式的视频格式都可以。只要我投入的工作量是最小的,我就可以使用标准播放器。
- 有人可以为我创建一个简短的清单吗?可以很漂亮bird-view。喜欢 "Create COM object which implements interfaces [list] - Use Mediafoundation codecs and whatnot [names] to build the pipeline - Implement IMFMediaSink in your sink object and get the data like...this ... The media clock is provided by (do I have to clock the pipeline from the back as it is a pull model or is the IMFMediaSink driven by some clock from within the session?) etc."?
- 如果我使用 h.264 编码器 - 我可以取回数据还是只渲染到文件?我是否需要额外的协议 headers 才能通过网络套接字进行流式传输?
由于我在 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 在内的网络流式传输有更好的支持。