我正在尝试将 RGB/NV12 样本编码为 h264,并通过实现 IMFByteStream 通过 SinkWriter 通过 WebSocket 流式传输编码的视频。在这个实验中,我使用像素着色器将 RGB32 样本转换为 NV12 样本。输出格式为带有 FMPEG4 容器的 H264。
我也尝试过直接输入 RGB 样本。通过软件方法它对 RGB 和 NV12 样本都可以正常工作,但是当取消注释下面提到的行时,WriteSample 失败并出现 E_FAIL 错误。不过,我正在正确设置 MF_SINK_WRITER_D3D_MANAGER。
COM_CHECK(attribs->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE));
Run Code Online (Sandbox Code Playgroud)
MFtrace 日志:
59980,EB60 10:18:27.65002 ### Exiting: traced process has exited
CMFPlatExportDetours::MFStartup @ Version=0x00020070, dwFlags=0x00000000
59980,EB60 10:18:27.65448 COle32ExportDetours::CoCreateInstance @ Created {60F9F51E-4613-4B35-AE88-332542B567B8} MF Fragmented MPEG4 Sink Class Factory (C:\WINDOWS\System32\mfmp4srcsnk.dll) @04B80148 - traced interfaces:
59980,EB60 10:18:27.65700 COle32ExportDetours::CoCreateInstance @ Created {9A02E012-6303-4E1E-B9A1-630F802592C5} Packed Property Storage Object (C:\WINDOWS\system32\propsys.dll) @012D5FEC - traced interfaces:
59980,EB60 10:18:27.65931 COle32ExportDetours::CoCreateInstance @ …Run Code Online (Sandbox Code Playgroud) 我一直在研究使用硬件加速的 h.264 编码和解码流式传输实时视频,并且我已经能够使用 Windows Media Foundation 使其工作。
我使用 d3d11 视频处理器将帧从 RGB 压缩为 NV12 格式,并使用硬件 MFT 编码为 h.264。
我现在唯一的问题是在解码和渲染视频后,锯齿和光晕效果与文本一起出现在屏幕上。
下面的图片显示了我的问题。
经过一番研究,我发现了H.264/AVC 444,其中微软通过引入带有 RDP 10 的全屏 AVC 444 模式解决了这个问题。
在 AVC 444 模式下,通过显着提高帧吞吐量,我们可以使用 4:2:0 硬件编码器/解码器获得 4:4:4 质量的文本。
介绍 AVC 444 模式 在远程桌面场景中使用 AVC/H.264 作为唯一的编解码器的主要挑战是文本显示具有典型 AVC/H.264 实现的光环效果。这是由作为压缩的一部分发生的颜色转换过程引起的,该过程丢弃了一些色度信息,如 4:2:0 格式所示。对于人眼来说,视频内容缺乏色度信息并不那么明显,但是对于主要使用文本的远程桌面场景,这是显而易见的,用户会认为这是模糊的。AVC/H.264 标准定义了使用 4:4:4 格式的能力,在转换过程中不会丢失色度,但是通常这不是大多数 AVC/H.264 硬件编码器和解码器实现的一部分,因此提供一个挑战。
我试图在 Media Foundation 中实现相同的目标,但尚未找到任何资源来破解它。
我发现颜色转换为 NV12 是这个问题背后的原因,我一直在努力解决它,我也尝试过 YUV 444,但找不到支持它的硬件 MFT。我无法使用硬件 MFT 编码除 NV12 之外的任何其他颜色格式
有什么办法可以克服这个问题吗?任何帮助将不胜感激。
directx video-streaming h.264 hardware-acceleration ms-media-foundation
我需要将视频帧从 RGB32 转换为 IYUV,但颜色转换器 MFT 拒绝处理样本。对于每一帧,我调用 IMFTransform::ProcessInput() 和 IMFTransform::ProcessOutput() 但我收到MF_E_TRANSFORM_NEED_MORE_INPUT。如果我尝试用另一个样品提供 MFT,我会收到MF_E_NOTACCEPTING错误。
下面我粘贴一个代码来显示我的问题。希望你们能帮上忙。
首先我创建媒体类型:
//DSP input MediaType
CHECK_HR(hr = MFCreateMediaType(&m_pInputMediaType));
CHECK_HR(hr = m_pInputMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
CHECK_HR(hr = m_pInputMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32))
CHECK_HR(hr = m_pInputMediaType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive))
CHECK_HR(hr = MFSetAttributeSize(m_pInputMediaType, MF_MT_FRAME_SIZE, m_pStreamParams->StreamWidth, m_pStreamParams->StreamHeight))
CHECK_HR(hr = MFSetAttributeRatio(m_pInputMediaType, MF_MT_FRAME_RATE, m_pStreamParams->StreamFramerate, 1))
CHECK_HR(hr = MFSetAttributeRatio(m_pInputMediaType, MF_MT_PIXEL_ASPECT_RATIO, 1, 1));
//DSP output MediaType
CHECK_HR(hr = MFCreateMediaType(&m_pIntermediateMediaType));
CHECK_HR(hr = m_pIntermediateMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
CHECK_HR(hr = m_pIntermediateMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV));
CHECK_HR(hr = m_pIntermediateMediaType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive));
CHECK_HR(hr = MFSetAttributeSize(m_pIntermediateMediaType, MF_MT_FRAME_SIZE, m_pStreamParams->StreamWidth, m_pStreamParams->StreamHeight));
CHECK_HR(hr = MFSetAttributeRatio(m_pIntermediateMediaType, …Run Code Online (Sandbox Code Playgroud) 我试图让我的编码器工作已经一周了......
所以事情是:
我使用 MF 的 Sink Writer 创建一个文件。
我写了所有的视频样本。
--> (如果我停在那里并调用 Finish 方法,我可以使用 VLC 读取该文件,但如果我执行以下操作,该文件将被“损坏”)
我写了所有的音频样本。
我调用完成函数,得到一个 HRESULT 代码:“接收器无法创建有效的输出文件,因为未向接收器提供所需的标头”。我完全理解这个错误,只是我不知道如何解决它......
如果你们需要任何代码,我很乐意将其放在这里。
我正在尝试使用URL直接从互联网播放M4A(MP4音频)文件.
我正在使用带有MediaFoundation的NAudio来实现这个目的:
using (var reader = new MediaFoundationReader(audioUrl)) //exception
using (var wave = new WaveOutEvent())
{
wave.Init(reader);
wave.Play();
}
Run Code Online (Sandbox Code Playgroud)
这适用于Windows 8.1和Windows 10的两个测试系统.但是在我的Windows 7机器上它无法工作,我从MediaFoundationReader构造函数中获得异常.
最初,我得到了一个ArgumentOutOfRangeException.我测试了在WMP中播放这个m4a文件,它也无法播放它.我下载了一个编解码器包并安装了它.这有助于WMP,但我的代码仍然抛出异常,尽管另一个:
NAudio.dll中发生了未经检查的"System.Runtime.InteropServices.COMException"类型的异常
附加信息:有更多可用数据.(HRESULT异常:0x800700EA)
什么可能导致这个以及我如何解决它?
我正在尝试在 Windows 10(桌面)上使用 DirectX 11 为 Media Foundation 编写 EVR。到目前为止,我找到的唯一一个解决方案是在这里 不幸的是,我不知道(和其他许多人一样)如何正确使用它。有人可以指出我如何将 MF 与 DirectX 11/12 结合的正确方向吗?
我正在使用激活我的 EVR 的代码:
hr = MFCreateVideoRendererActivate(hwndVideo, &pRendererActivate);
hr = pRendererActivate->SetGUID(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID, CLSID_DX11VideoRenderer);
Run Code Online (Sandbox Code Playgroud)
我来到了 MF 要求 GetDeviceID 并在 kernel.dll 中引发异常的地步。我认为混合器和渲染器设备之间存在不匹配。它们的默认设备是 DX9。在我的示例中,我必须提供 DirectX 11 设备 CLSID。
我正在使用 Windows Media Foundation 创建视频文件。我有一些基于使用接收器编写器编码视频教程的代码。
当输入类型为MFVideoFormat_RGB32,输出类型为MFVideoFormat_WMV3,并且接收器编写器正在写入 WMV 文件,并且我为接收器编写器提供自上而下的 RGB32 数据时,我得到了我期望的视频。
MFVideoFormat_H264另一方面,当输出类型为 时- 其他一切都相同 - 位图会颠倒过来。
如何在运行时找出需要哪种位图数据?
我正在尝试将 H.264 视频源流式传输到网络浏览器。Media Foundation 用于对分段的 MPEG4 流进行编码(MFCreateFMPEG4MediaSink使用MFTranscodeContainerType_FMPEG4、MF_LOW_LATENCY和MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS启用)。然后,该流通过 .NET 连接到 Web 服务器IMFByteStream。
当 H.264 视频被标签使用时,它的流式传输工作正常<video src=".."/>。然而,产生的延迟约为 2 秒,这对于相关应用程序来说太大了。我怀疑客户端缓冲导致了大部分延迟。因此,我正在尝试使用媒体源扩展 (MSE) 对浏览器内流进行编程控制。但是,当通过 MSE 使用相同的 MPEG4 流时,Chrome 会失败并出现以下错误:
解析 MP4 失败:MSE 不允许 TFHD 基本数据偏移。请参阅 https://www.w3.org/TR/mse-byte-stream-format-isobmff/#movie-fragment-relative-addressing
MPEG4 流中 moof/mdat 片段的 mp4dump。这清楚地表明 TFHD 包含“非法”base data offset参数:
[moof] size=8+200
[mfhd] size=12+4
sequence number = 3
[traf] size=8+176
[tfhd] size=12+16, flags=1
track ID = 1
base data offset = 36690
[trun] size=12+136, version=1, flags=f01 …Run Code Online (Sandbox Code Playgroud) 在Windows 10上,需要访问网络摄像头的应用程序,与之通信frame server的服务进行通信svchost.
我过滤掉了网络摄像头流和我得到的进程ID svchost.我想确定使用网络摄像头的实际过程.
有没有明确的方法来以编程方式识别使用网络摄像头的实际应用程序是什么?我已经研究了枚举进程的句柄(也必须处理NtQueryObject()挂起),但我正在寻找更好的解决方案.
我正在编写一个Media Foundation应用程序,以从60Hz的UVC摄像机获取并显示1920x1080 YUV2图像。
我的问题是ReadSample()回调仅以非常低的速率(大约1 FPS)被不稳定地调用,只有几帧的突发。
这发生在两台笔记本电脑上,但是到目前为止我还没有尝试过使用台式机。我正在运行Windows 10,并且我在其上进行测试的所有计算机都是最新的。
但是,我注意到,如果我让CPU忙于我的应用程序,则回调将按预期以60Hz进行调用。
编辑
注意:当CPU由于反病毒启动而繁忙时,回调率也会提高。虽然没有达到完整的60Hz。
因此,如果我将消息循环从以下位置更改:
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Run Code Online (Sandbox Code Playgroud)
至:
while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
Run Code Online (Sandbox Code Playgroud)
然后FPS回到60Hz;但当然CPU使用率接近100%...
同上,使用第一个消息循环将鼠标移到窗口上方会使FPS增加一点(〜10FPS)。
将摄像机的帧速率降低到30Hz会导致ReadSample()回调以应有的30Hz发生。
我已经从Microsoft提供的示例(“ Windows经典示例”)中复制了MFCaptureD3D示例的相同问题。
注意,我对示例进行了一些修改,以测量ReadSample()回调中的帧速率。
在我的笔记本电脑上,该示例的大小约为25FPS(因此丢掉了很多帧)。这是因为色彩空间转换是基于CPU的并且效率很低(一个内核的75%)。但是,它仍然管理25PFS!
注释掉转换(没有其他代码更改),导致帧速率下降到几乎为零!... CPU使用率为0%。因此,回调不会发生。
在两个应用程序中,COM库都在应用程序的主线程中初始化(运行窗口的消息循环),如下所示:
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
Run Code Online (Sandbox Code Playgroud)
为了方便起见,我从Microsoft的示例复制了ReadSample()回调:
HRESULT CPreview::OnReadSample(HRESULT hrStatus, DWORD /* dwStreamIndex */, DWORD /* dwStreamFlags */, LONGLONG /* llTimestamp */, IMFSample *pSample)
{
HRESULT hr = S_OK;
IMFMediaBuffer *pBuffer = NULL;
EnterCriticalSection(&m_critsec);
if (FAILED(hrStatus))
hr = hrStatus; …Run Code Online (Sandbox Code Playgroud)