IMFSinkWriter 无法导出 mp4 的大尺寸视频

2022-01-12 00:00:00 windows c++ video mfc ms-media-foundation

我的 Windows MFC 应用程序具有导出视频文件的功能.
它可以选择编码格式(通过WMV或MP4)和帧大小.
但是,不幸的是,当我尝试导出设置为大帧大小的 MP4 文件时,每次 MF_E_INVALIDMEDIATYPE 都会发生.

My Windows MFC application has a function to export a video file.
And it can select encoding format (via WMV or MP4) and frame size.
But, Unfortunately when i tried to export MP4 file which is set large frame size, everytime MF_E_INVALIDMEDIATYPE happened.

简单地说,这是我在每种情况下测试时的结果.

Simply put, here is the result when i tested in each case.

  • 640 x 480 ...好的
  • 640 x 576 ... 好的
  • 1280 x 720 ... 好的
  • 1280 x 720 ... 好的
  • 1920 x 1080 ... 好的
  • 2048 x 1556 ... 好的
  • 4096 x 2160 ... 好的
  • 640 x 480 ...好的
  • 640 x 576 ... 好的
  • 1280 x 720 ... 好的
  • 1280 x 720 ... 好的
  • 1920 x 1080 ... 好的
  • 2048 x 1556 ... MF_E_INVALIDMEDIATYPE
  • 4096 x 2160 ... MF_E_INVALIDMEDIATYPE

这是我的代码.

HRESULT hr = S_OK;
TIFF *out;
IMFSinkWriter   *pWriter = NULL;
IMFMediaType    *pMediaTypeOut = NULL;   
IMFMediaType    *pMediaTypeIn = NULL;   
DWORD           streamIndex;     

hr = MFCreateSinkWriterFromURL(filename, NULL, NULL, &pWriter);

// Set the output media type.
if (SUCCEEDED(hr))
{
  hr = MFCreateMediaType(&pMediaTypeOut);   
}
if (SUCCEEDED(hr))
{
  hr = pMediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);     
}
if (SUCCEEDED(hr))
{
  if (exportMethod == ExportFormatWAV) {
    hr = pMediaTypeOut->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_WVC1);
  }
  else if (exportMethod == ExportFormatMP4) {
    hr = pMediaTypeOut->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264);   
  }
}
if (SUCCEEDED(hr))
{
  hr = pMediaTypeOut->SetUINT32(MF_MT_AVG_BITRATE, 12 * 1000 * 1000); // 12M   
}
if (SUCCEEDED(hr))
{
  hr = pMediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);   
}
if (SUCCEEDED(hr))
{
  hr = MFSetAttributeSize(pMediaTypeOut, MF_MT_FRAME_SIZE, m_width, m_height);   // e.g. 4096 x 2160
}
if (SUCCEEDED(hr))
{
  hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_FRAME_RATE, m_fps * 100, 100);   
}
if (SUCCEEDED(hr))
{
  hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_PIXEL_ASPECT_RATIO, 1, 1);   
}
if (SUCCEEDED(hr))
{
  hr = pWriter->AddStream(pMediaTypeOut, &streamIndex);   
}

// Set the input media type.
if (SUCCEEDED(hr))
{
  hr = MFCreateMediaType(&pMediaTypeIn);   
}
if (SUCCEEDED(hr))
{
  hr = pMediaTypeIn->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);   
}
if (SUCCEEDED(hr))
{
  if (exportMethod == ExportFormatWAV) {
    hr = pMediaTypeIn->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24);   
  }
  else if (exportMethod == ExportFormatMP4) {
    hr = pMediaTypeIn->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32);     // Because H264 requires
  }
}
if (SUCCEEDED(hr))
{
  hr = pMediaTypeIn->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);   
}
if (SUCCEEDED(hr))
{
  hr = MFSetAttributeSize(pMediaTypeIn, MF_MT_FRAME_SIZE, m_width, m_height);   // e.g. 4096 x 2160
}
if (SUCCEEDED(hr))
{
  hr = MFSetAttributeRatio(pMediaTypeIn, MF_MT_FRAME_RATE, m_fps * 100, 100);   
}
if (SUCCEEDED(hr))
{
  hr = MFSetAttributeRatio(pMediaTypeIn, MF_MT_PIXEL_ASPECT_RATIO, 1, 1);   
}
if (SUCCEEDED(hr))
{
  hr = pWriter->SetInputMediaType(streamIndex, pMediaTypeIn, NULL);   // This line returns MF_E_INVALIDMEDIATYPE
}

// Tell the sink writer to start accepting data.
if (SUCCEEDED(hr))
{
  hr = pWriter->BeginWriting();
}

我也想导出 MP4 的大尺寸视频.
有谁知道解决这个问题的方法吗?

I want to export a large sized video of MP4 as well.
Does anyone know a solution against this problem?

参考
https://msdn.microsoft.com/en-us/library/windows/desktop/ff819477(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/ff819476(v=vs.85).aspx

msdn 已经发布了同样的问题.
https://social.msdn.microsoft.com/Forums/en-US/ac5b71e4-e94a-4d18-bc92-8b44fa5280b6/the-max-resolution-for-mp4h264-encoder

Same question has already posted msdn.
https://social.msdn.microsoft.com/Forums/en-US/ac5b71e4-e94a-4d18-bc92-8b44fa5280b6/the-max-resolution-for-mp4h264-encoder

推荐答案

Media Foundation 的 MPEG-4 文件接收器 没有分辨率限制.它多路复用已经编码的数据,并且对视频分辨率不敏感.

Media Foundation's MPEG-4 File Sink has no resolution restrictions. It multiplexes already encoded data and is not sensitive to video resolution.

但是,如果/当您对 H.264 上下文进行编码时,编码器通常确实存在限制.例如,英特尔(R) HD Graphics 4600 的英特尔? 快速同步视频 H.264 编码器 MFT 可以生成 4096 x 4096 H.264 内容,并且 MP4 接收器将其正确写入文件.

If/when you, however, are encoding H.264 context, the encoders typically do have the limitations. For example, Intel(R) HD Graphics 4600's Intel? Quick Sync Video H.264 Encoder MFT can produce 4096 x 4096 H.264 content, and MP4 sink writes it correctly to file.

在您的情况下,您可能会达到编码器的分辨率限制,并且由于编码器使用通用错误代码拒绝不受支持的分辨率,因此您没有比 MF_E_INVALIDMEDIATYPE 更有帮助的东西了.使用备用编码器可能会更好.

In your case you are likely to hit resolution limit in encoder, and since encoder rejects unsupported resolution with generic error code, you don't have anything more helpful than MF_E_INVALIDMEDIATYPE. You might have better luck with an alternate encoder.

相关文章