Microsoft Media Foundation(MF)是Windows Vista中DirectShow的继承者.我大多忽略它,但它有一些功能(如WMV AC-1文件的解码)很难在DirectShow中实现.Media Foundation也是一个更现代化的API,因此进行切换似乎合乎逻辑.
但是,在线教学资源和官方文档似乎非常缺乏.只有一本书涉及该主题(由微软出版),它不再适用于正常价格.(人们收取500美元,或者更多的二手版本.)
据我所知,没有其他书籍.虽然微软的其他技术通常由多个出版商在多本书中涵盖.
Media Foundation的官方博客自2011年以来一直没有更新.在活跃的两年中,只写了10篇技术文章,其中5篇涉及错误记录/跟踪而不是实际功能.
StackOverflow标签ms-media-foundation仅用于328个问题,其中142个未得到答复.相比之下,有1641个DirectShow问题,其中只有496个未得到答复.
那么微软媒体基金会发生了什么?这个新的API是否会起飞并取代DirectShow,甚至微软还会抛弃MF,转而回到旧的和生锈的(可靠的?)DirectShow.或者是否有另一个非Microsoft框架已经接管了?
我正在尝试在视频捕获/监控/流媒体应用程序中选择这两个API,我不确定哪个是最好的选择.
一点背景:
一些谷歌搜索给我的印象是
MF认为前进更好,但我担心如果MF没有"赶上"并且Directshow仍然是首选的API,那么最终会陷入技术死胡同.建议和建议,请...
我的应用程序是捕获桌面屏幕(屏幕共享)并发送到其他设备.目前应用程序使用以下方法捕获屏幕
- 使用GDI(Bitblt)
- 使用DirectX(getFrontBufferData)
-
根据Windows版本和用例使用DXGI(桌面复制API),应用程序使用其中一个.
我正在寻找硬件加速api,它比现有的实现更快地完成这项工作.作为参考,我们在Mac OS中有一些东西点击这里.
在Windows中搜索硬件加速屏幕捕获之后,找到了以下一些选项:
- 基于GDI的捕获
- 它是一个常用的软件捕获库,它支持Windows 7中的硬件加速.
- 基于Directx的捕获
- 一些选项提出了以下参考文献中提到的direct3d9和direct3d11捕获.在directx方法中使用getfrontbufferData比gdi本身慢.
- 基于DXGI的捕获
- 它支持Windows 8和更高版本的Windows,它是我的应用程序中的direct3d11基础实现.
- 基于Windows媒体编码器9的捕获
参考文献:http://www.codeproject.com/Articles/5051/Various-methods-for-capturing-the-screen和
最快的屏幕捕获方法
但是这些引用看起来很旧,有没有最新版Windows中的此类功能.
前三种方法已经在我的应用程序中以某种方式使用.DXGI在某种程度上更好,因为它具有硬件加速(使用GPU).
我正在寻找一个类似于上部提到的mac应用程序的Windows应用程序/库.我们的用例很简单,可以在不影响系统性能的情况下以最佳方式捕获屏幕框架(我希望只有使用GPU才能实现,这将节省cpu周期).
我正在尝试使用Windows Media Foundation将从图像(RGBA)源(桌面/相机)捕获的RGBA缓冲区编码为原始H264,传输它们并实时解码在另一端接收的原始H264帧。我正在尝试至少达到30 fps。编码器工作得很好,但解码器却不能。
我了解Microsoft WMF MFT在发出编码/解码数据之前最多缓冲30帧。
图像源仅在发生变化时才会发出帧,而不是连续的RGBA缓冲区流,因此,我的目的是为每个MFT的每个输入缓冲区获得一个编码/解码数据的缓冲区,以便我可以流式传输实时数据并进行渲染。
当我使图像源发送连续更改(通过刺激更改)时,编码器和解码器均能够发出至少10到15 fps的帧。编码器能够利用硬件加速支持。我能够在编码器端达到30 fps,并且还没有使用DirectX表面实现硬件辅助解码。这里的问题不是帧速率,而是MFT对数据的缓冲。
因此,我尝试通过发送MFT_MESSAGE_COMMAND_DRAIN命令并反复调用ProcessOutput直到解码器返回MF_E_TRANSFORM_NEED_MORE_INPUT来消耗解码器MFT 。现在发生的事情是,解码器现在每30个输入h264缓冲区仅发出一帧,我甚至用连续的数据流对其进行了测试,其行为是相同的。好像解码器将所有中间帧都丢弃在GOP中。
如果只缓冲前几个帧,这对我来说是可以的,但是即使在SPS和PPS解析阶段之后,我的解码器实现也仅在其缓冲区一直充满时才输出。
我遇到了Google的铬源代码(https://github.com/adobe/chromium/blob/master/content/common/gpu/media/dxva_video_decode_accelerator.cc),它们遵循相同的方法。
mpDecoder->ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, NULL);
Run Code Online (Sandbox Code Playgroud)
我的实现基于 https://github.com/GameTechDev/ChatHeads/blob/master/VideoStreaming/EncodeTransform.cpp
和
https://github.com/GameTechDev/ChatHeads/blob/master/VideoStreaming/DecodeTransform.cpp
我的问题是,我想念什么吗?Windows Media Foundation是否适合实时流?排干编码器和解码器是否适用于实时用例?
对于我来说,只有两个选择,使此WMF可以作为实时用例工作,或者与Intel的QuickSync等一起使用。我选择WMF作为我的POC,因为在任何MFT不可用的情况下Windows Media Foundation隐式支持硬件/ GPU /软件后备,并且在内部无需太多编码即可选择最佳的MFT。
我遇到了视频质量问题,尽管bitrate属性设置为3Mbps。但是与缓冲问题相比,它的优先级最低。数周来,我一直在敲打键盘,这很难修复。任何帮助,将不胜感激。
码:
编码器设置:
IMFAttributes* attributes = 0;
HRESULT hr = MFCreateAttributes(&attributes, 0);
if (attributes)
{
//attributes->SetUINT32(MF_SINK_WRITER_DISABLE_THROTTLING, TRUE);
attributes->SetGUID(MF_TRANSCODE_CONTAINERTYPE, MFTranscodeContainerType_MPEG4);
}//end if (attributes)
hr = MFCreateMediaType(&pMediaTypeOut);
// Set the output media type.
if (SUCCEEDED(hr))
{
hr = MFCreateMediaType(&pMediaTypeOut);
}
if (SUCCEEDED(hr))
{
hr = pMediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用Windows10上的Live555和Windows Media Foundation的硬件编码器通过RTP流将桌面(NV12格式的DirectX表面)流化为H264视频,并期望由ffplay(ffmpeg 4.2)渲染。但是只有如下所示的绿屏,
我使用硬件MFT引用了MFWebCamToRTP mediafoundation-sample和Encoding DirectX表面,以实现live555的FramedSource并将输入源更改为DirectX表面而不是webCam。
这是我的Live555的doGetNextFrame回调实现的摘录,以从directX表面提供输入样本:
virtual void doGetNextFrame()
{
if (!_isInitialised)
{
if (!initialise()) {
printf("Video device initialisation failed, stopping.");
return;
}
else {
_isInitialised = true;
}
}
//if (!isCurrentlyAwaitingData()) return;
DWORD processOutputStatus = 0;
HRESULT mftProcessOutput = S_OK;
MFT_OUTPUT_STREAM_INFO StreamInfo;
IMFMediaBuffer *pBuffer = NULL;
IMFSample *mftOutSample = NULL;
DWORD mftOutFlags;
bool frameSent = false;
bool bTimeout = false;
// Create sample
CComPtr<IMFSample> videoSample = NULL;
// Create buffer
CComPtr<IMFMediaBuffer> …Run Code Online (Sandbox Code Playgroud) 我正在使用DesktopDuplication API捕获桌面,并将示例从RGBA转换为GPU中的NV12,并将其提供给MediaFoundation硬件H264 MFT。这在Nvidia图形以及软件编码器上都可以正常工作,但是在只有Intel图形硬件MFT可用时失败。如果我退回到Software MFT,该代码在同一台Intel图形计算机上也可以正常工作。我还确保了编码实际上是在Nvidia图形计算机上的硬件中完成的。
在Intel图形上,MFT返回MEError(“未指定错误”),仅在馈入第一个样本后才发生,随后对ProcessInput的调用(当事件生成器触发METransformNeedInput时)返回“被调用方当前不接受进一步的输入”。MFT很少会在返回这些错误之前消耗更多的样本。这种行为令人困惑,仅当事件生成器通过IMFAsyncCallback异步触发METransformNeedInput时,我才提供示例,并且还应检查提供示例后是否立即触发METransformHaveOutput。当相同的异步逻辑与Nvidia硬件MFT和Microsoft软件编码器一起正常工作时,这真让我感到困惑。
英特尔论坛本身也有一个类似的未解决问题。我的代码类似于intel线程中提到的代码,除了我还将d3d设备管理器设置为如下所示的编码器这一事实。
并且,还有其他三个堆栈溢出线程报告了类似的问题,但没有给出解决方案(MFTransform编码器-> ProcessInput返回E_FAIL& 如何从D11纹理为Intel MFT编码器创建IMFSample&异步MFT没有发送MFTransformHaveOutput事件(Intel硬件MJPEG解码器MFT))。我尝试了所有可能的选择,对此没有任何改进。
颜色转换器代码取自intel media sdk示例。我也在这里上传了完整的代码。
设置d3d管理器的方法:
void SetD3dManager() {
HRESULT hr = S_OK;
if (!deviceManager) {
// Create device manager
hr = MFCreateDXGIDeviceManager(&resetToken, &deviceManager);
}
if (SUCCEEDED(hr))
{
if (!pD3dDevice) {
pD3dDevice = GetDeviceDirect3D(0);
}
}
if (pD3dDevice) {
// NOTE: Getting ready for multi-threaded operation
const CComQIPtr<ID3D10Multithread> pMultithread = pD3dDevice;
pMultithread->SetMultithreadProtected(TRUE);
hr = deviceManager->ResetDevice(pD3dDevice, resetToken);
CHECK_HR(_pTransform->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, reinterpret_cast<ULONG_PTR>(deviceManager.p)), …Run Code Online (Sandbox Code Playgroud) directx video-streaming h.264 hardware-acceleration ms-media-foundation
我正在使用Media Foundation IMFSourceReaderCallback实现从相机中抓取视频帧,然后使用OpenCV imshow来循环显示帧.
但是我把框架垂直翻转......
这是一个错误吗?我应该设置一些属性来避免这种情况吗?
这是我的代码:
初始化:
IMFAttributes* pDeviceAttrs, *pReaderAttrs;
hr = MFCreateAttributes(&pDeviceAttrs, 1);
if (FAILED(hr)) goto Exit;
hr = pDeviceAttrs->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);
if (FAILED(hr)) goto Exit;
//...
// Correct source provider is activated through ActivateObject
//
hr = MFCreateAttributes(&pReaderAttrs, 2);
if (FAILED(hr)) goto Exit;
pReaderAttrs->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK,(IUnknown*)this);
pReaderAttrs->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE);
hr = MFCreateSourceReaderFromMediaSource(pMediaSource, pReaderAttrs, &m_pReader);
if (FAILED(hr)) goto Exit;
// Correct profile is set
Run Code Online (Sandbox Code Playgroud)
OnReadSample实现:
HRESULT hr = S_OK;
LONG defaultStride = 0;
LONG stride = 0;
BYTE *pBuffer = …Run Code Online (Sandbox Code Playgroud) 我正在编写一个代码,以使用桌面复制捕获桌面,并使用英特尔hardwareMFT将其编码为h264。编码器仅接受NV12格式作为输入。我有一个DXGI_FORMAT_B8G8R8A8_UNORM到NV12转换器(https://github.com/NVIDIA/video-sdk-samples/blob/master/nvEncDXGIOutputDuplicationSample/Preproc.cpp)可以正常工作,并且基于DirectX VideoProcessor。
问题是某些英特尔图形硬件上的VideoProcessor仅支持从DXGI_FORMAT_B8G8R8A8_UNORM到YUY2的转换,但不支持NV12的转换,我已经通过GetVideoProcessorOutputFormats枚举支持的格式来确认了相同的转换。尽管VideoProcessor Blt成功实现,没有任何错误,而且我可以看到输出视频中的帧有些像素化,但是如果仔细观察它,我会注意到它。
我猜想,VideoProcessor只是故障转移到了下一个受支持的输出格式(YUY2),而我在不知不觉中将其馈送到认为输入已按照配置在NV12中的编码器。NV12和YUY2之间几乎没有像字节顺序和子采样之类的差异,因此不会出现帧故障或严重损坏的情况。另外,在支持NV12转换的硬件上我也没有像素化问题。
所以我决定使用基于此代码的像素着色器进行颜色转换(https://github.com/bavulapati/DXGICaptureDXColorSpaceConversionIntelEncode/blob/master/DXGICaptureDXColorSpaceConversionIntelEncode/DuplicationManager.cpp)。我能够使像素着色器正常工作,我也已经在这里上传了我的代码(https://codeshare.io/5PJjxP)供参考(尽可能简化了它)。
现在,我剩下两个通道,分别是色度和亮度(ID3D11Texture2D纹理)。对于将两个独立的通道有效地打包到一个ID3D11Texture2D纹理中,以便将其提供给编码器,我确实感到困惑。有没有一种方法可以将Y和UV通道有效地打包到GPU中的单个ID3D11Texture2D中?我非常厌倦基于CPU的方法,因为它价格昂贵,并且无法提供最佳的帧速率。实际上,我什至不愿意将纹理复制到CPU。我正在考虑一种在GPU中执行此操作的方法,而无需在CPU和GPU之间来回复制。
我已经对此进行了相当长时间的研究,没有任何进展,我们将不胜感激。
/**
* This method is incomplete. It's just a template of what I want to achieve.
*/
HRESULT CreateNV12TextureFromLumaAndChromaSurface(ID3D11Texture2D** pOutputTexture)
{
HRESULT hr = S_OK;
try
{
//Copying from GPU to CPU. Bad :(
m_pD3D11DeviceContext->CopyResource(m_CPUAccessibleLuminanceSurf, m_LuminanceSurf);
D3D11_MAPPED_SUBRESOURCE resource;
UINT subresource = D3D11CalcSubresource(0, 0, 0);
HRESULT hr = m_pD3D11DeviceContext->Map(m_CPUAccessibleLuminanceSurf, subresource, D3D11_MAP_READ, 0, &resource);
BYTE* sptr = reinterpret_cast<BYTE*>(resource.pData);
BYTE* dptrY = nullptr; // point to the address of …Run Code Online (Sandbox Code Playgroud) 我有一个H264流(IIS - 流畅的流),我想与SilverLight一起玩.显然SilverLight可以做到,但是怎么做?
注意:
SilverLight可以播放VC-1流,但不能播放H264.
此外,我可以提供流和所需的任何其他信息.H264编码器是Media Foundation(MFT)中的编码器.同样适用于VC-1(虽然不可能为平滑流创建相同的块,因为强制关键帧插入会导致视频不稳定.
编辑:H264的MPEG2VIDEOINFO值:
silverlight video-streaming h.264 smooth-streaming ms-media-foundation
我的任务是修改一个使用DirectShow进行视频渲染的应用程序.旧的应用程序工作正常,但它开始显示年龄.
由于我有游戏背景,我想我应该这样做.在使用不同的技术制作了一堆原型之后,我非常确定我可以提取视频到纹理的渲染并使用DirectX来满足所有客户的请求.
但是,我现在已经到了必须选择一种技术的地步,我不能再迷失了......
DirectShow显然是最古老的,但仍然运行良好,也主要是因为可用的大量编解码器.
媒体基金会已经推出了Windows Vista,直到Windows 8还有一个名为"媒体会话"的东西,之后他们推出了"媒体引擎".如果我是正确的编解码器被称为MFT?实际上有哪些网站可以像free-codecs.com一样提供这些网站?
除了这两种技术之外,还有DXVA,它允许您将视频解码卸载到GPU.目前,我遇到了3种不同的类型.DXVA1是自XP以来一直存在的实现,DXVA2是更新的API.但什么是DXVA-HD?它比DXVA2更新还是同等名称?
我真的想转向媒体基金会,开箱即用的编解码器非常适合客户想要使用的格式.我所关心的是为它获取编解码器是多么容易...... Windows 8+默认媒体播放器是否仍然具有DirectShow和MF渲染路径并且可以即时交换它们还是微软完全逐步淘汰DirectShow?
我也无法完全理解DXVA应该如何工作.鉴于我想基本上在游戏中渲染视频,只有让所有渲染实际发生在GPU上并将应用程序逻辑保留在CPU上才有意义,但我真的找不到任何关于如何使用Media的好例子基础.这主要是因为我不知道DXVA2和DXVA-HD之间的区别.Windows 7 SDK附带了所有3个实现的示例......
如果有人能够以粗体回答我的问题,请纠正我的错误信息,并指出我正确的方向(DirectX + Media Foundation + DXVA-无论如何),我将非常感激!它可以像"结合Windows 7 SDK的这3个示例来获得您想要的"一样简单.
整个任务的目标是再次获得顶级形式的应用程序,我想绝对肯定我会选择像DirectShow已经拥有的下一个十年的技术:P
directx ×6
h.264 ×4
c++ ×3
directshow ×2
windows ×2
directx-11 ×1
dxva ×1
ffmpeg ×1
pixel-shader ×1
silverlight ×1
video ×1
yuv ×1