对不起我的英语。我对Windows 10中使用MF的硬件编码有疑问,我有Nvidia gtx 650 (与nvenc)。我在c#中开发了将活动帧流编码为c#文件的应用程序。
我以这段代码( https://codereview.stackexchange.com/questions/136144/h-264-image-encoding-using-media-foundation-net )为例。我创建了IMFSinkWriter对象(SinkWriter),例如,使用MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS=true
private int InitializeSinkWriter(String outputFile, int videoWidth, int videoHeight)
{
IMFMediaType mediaTypeIn = null;
IMFMediaType mediaTypeOut = null;
IMFAttributes attributes = null;
int hr = 0;
if (Succeeded(hr)) hr = MFExtern.MFCreateAttributes(out attributes, 1);
if (Succeeded(hr)) hr = attributes.SetUINT32(MFAttributesClsid.MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, 1);
if (Succeeded(hr)) hr = attributes.SetUINT32(MFAttributesClsid.MF_LOW_LATENCY, 1);
// Create the sink writer
if (Succeeded(hr)) hr = MFExtern.MFCreateSinkWriterFromURL(outputFile, null, attributes, out sinkWriter);
// Create the output type
if (Succeeded(hr)) hr = MFExtern.MFCreateMediaType(out mediaTypeOut);
if (Succeeded(hr)) hr = mediaTypeOut.SetGUID(MFAttributesClsid.MF_MT_MAJOR_TYPE, MFMediaType.Video);
if (Succeeded(hr)) hr = mediaTypeOut.SetGUID(MFAttributesClsid.MF_MT_SUBTYPE, MFMediaType.H264);
if (Succeeded(hr)) hr = mediaTypeOut.SetUINT32(MFAttributesClsid.MF_MT_AVG_BITRATE, videoBitRate);
if (Succeeded(hr)) hr = mediaTypeOut.SetUINT32(MFAttributesClsid.MF_MT_INTERLACE_MODE, (int) MFVideoInterlaceMode.Progressive);
if (Succeeded(hr)) hr = MFExtern.MFSetAttributeSize(mediaTypeOut, MFAttributesClsid.MF_MT_FRAME_SIZE, videoWidth, videoHeight);
if (Succeeded(hr)) hr = MFExtern.MFSetAttributeRatio(mediaTypeOut, MFAttributesClsid.MF_MT_FRAME_RATE, VIDEO_FPS, 1);
if (Succeeded(hr)) hr = MFExtern.MFSetAttributeRatio(mediaTypeOut, MFAttributesClsid.MF_MT_PIXEL_ASPECT_RATIO, 1, 1);
if (Succeeded(hr)) hr = sinkWriter.AddStream(mediaTypeOut, out streamIndex);
// Create the input type
if (Succeeded(hr)) hr = MFExtern.MFCreateMediaType(out mediaTypeIn);
if (Succeeded(hr)) hr = mediaTypeIn.SetGUID(MFAttributesClsid.MF_MT_MAJOR_TYPE, MFMediaType.Video);
if (Succeeded(hr)) hr = mediaTypeIn.SetGUID(MFAttributesClsid.MF_MT_SUBTYPE, MFMediaType.RGB24);
if (Succeeded(hr)) hr = mediaTypeIn.SetUINT32(MFAttributesClsid.MF_MT_INTERLACE_MODE, (int)MFVideoInterlaceMode.Progressive);
if (Succeeded(hr)) hr = MFExtern.MFSetAttributeSize(mediaTypeIn, MFAttributesClsid.MF_MT_FRAME_SIZE, videoWidth, videoHeight);
if (Succeeded(hr)) hr = MFExtern.MFSetAttributeRatio(mediaTypeIn, MFAttributesClsid.MF_MT_FRAME_RATE, VIDEO_FPS, 1);
if (Succeeded(hr)) hr = MFExtern.MFSetAttributeRatio(mediaTypeIn, MFAttributesClsid.MF_MT_PIXEL_ASPECT_RATIO, 1, 1);
if (Succeeded(hr)) hr = sinkWriter.SetInputMediaType(streamIndex, mediaTypeIn, null);
// Start accepting data
if (Succeeded(hr)) hr = sinkWriter.BeginWriting();
COMBase.SafeRelease(mediaTypeIn);
COMBase.SafeRelease(mediaTypeOut);
return hr;
}例如,我为每个帧编码执行了以下步骤: 1.创建IMFMediaBuffer对象(缓冲区)并在其中复制框架2.创建IMFSample对象(示例)和sample.AddBuffer(缓冲区) 3.将示例写入IMFSinkWriter对象(SinkWriter)
结果是CPU上有100%的负载(这不是硬件编码!)。如何使用相同的代码进行硬件编码?
发布于 2016-11-29 12:07:36
接收器写入器API为您提供自动转换(尤指。(编码)的数据,当您请求时,它依次包括H.264编码。您确实是通过用MFMediaType.H264执行AddStream,然后用MFMediaType.RGB24执行SetInputMediaType来请求它。
但是,您没有选择编码器的细粒度灵活性。API是通过设计为您选择“最佳”编码器的行为。您的应用MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS意味着您可以使用硬件MFT,但这并不意味着您强制选择。你甚至不知道硬件MFT一开始是否可行,是吗?再一次,API通过设计的行为避免了所谓的“编解码地狱”的模糊性,保留了选择最佳适用编码器本身的权利。文档以这样的方式解释:如果存在经过认证的硬件编码器,则通常会使用它来代替媒体基金会相关场景中的收件箱系统编码器。
最大的CPU负载是一个提示,压缩可能是软件,但它也可能是由其他原因造成的。在您的情况下,您需要检查哪些H.264编码器可用,调试和跟踪您的应用程序。当API不自动拾取编码器时,要强制使用Media Foundation进行硬件H.264编码,您没有其他选择,只能自己将视频压缩到H.264 (使用MFT,它对应于编码器以MFT的形式存在但API不拾取它的不太可能的情况,或者编码否则esp )。使用特定于供应商的SDK),然后将压缩数据提供给Sink Writer以生成格式良好的MP4文件,可能还会混合音频。
另请参阅:
您可以使用MediaFoundationVideoEncoderTransforms工具检查硬件编码器的可用性。
https://stackoverflow.com/questions/40853446
复制相似问题