【问题标题】:Convert IMFMediaBuffer data having data type of YUY2 to RGB24 or RGB32将数据类型为 YUY2 的 IMFMediaBuffer 数据转换为 RGB24 或 RGB32
【发布时间】:2022-03-07 18:22:43
【问题描述】:

我正在使用 MediaFoundation APIS 从我的网络摄像头读取帧。

IMFMediaType mediatype = null;
Hresult hr= mSourceReaderAsync.GetNativeMediaType((int)MF_SOURCE_READER.FirstAudioStream, i, out mediatype); 

只返回 YUY2 媒体类型。所以我得到的 ReadSample 的输出给出了 YUY2 帧。我需要将 YUY2 转换为 RGB24 或 BitmapSource 以显示在 WPF 窗口中。 这是我的 OnRead 回调方法

 public HResult OnReadSample(HResult hrStatus, int dwStreamIndex, MF_SOURCE_READER_FLAG dwStreamFlags, long llTimestamp, IMFSample pSample)
{
    HResult hr = hrStatus;
    IMFMediaBuffer pBuffer = null;
    Stream s = null;
    JpegBitmapDecoder jpgdecoder = null; 
    BitmapSource cameraframe = null; 
    lock (this)
    {
        try
        {
            if (Succeeded(hr))
            {
                if (pSample != null)
                {
                    // Get the video frame buffer from the sample.
                    hr = pSample.GetBufferByIndex(0, out pBuffer);
                }
            }
            if (pBuffer != null)
            {
                int maxlen, curlen;
                pBuffer.GetMaxLength(out maxlen);
                pBuffer.GetCurrentLength(out curlen);
                var arr = new byte[maxlen - 1];
                pBuffer.Lock(out IntPtr ptr, out int maxLen, out int curLen);
                if (arr == null)
                    arr = new byte[maxlen - 1];
                var writable = (maxlen > 0) ? true : false;
                if (s == null)
                    s = new MemoryStream(arr, writable);

                System.Runtime.InteropServices.Marshal.Copy(ptr, arr, 0, curlen);


                s.Flush();
                s.Seek(0, SeekOrigin.Begin);
                if (jpgdecoder == null)
                    jpgdecoder = new JpegBitmapDecoder(s, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);

                var frame = jpgdecoder.Frames[0];
                cameraframe = frame;
            }
            dispatcher.Invoke(() =>
            {
                OnCapture.Invoke(this, cameraframe);
            });
            // Request the next frame.
            if (Succeeded(hr))
            {
                // Ask for the first sample.
                
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
        finally
        {
            SafeRelease(pBuffer);
            SafeRelease(pSample);
            dispatcher.Invoke(() =>
            {
                hr = mSourceReaderAsync.ReadSample((int)MF_SOURCE_READER.FirstVideoStream, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
            });
        }
    }

    return hr;
}

现在它引发异常{“未找到适合完成此操作的成像组件。”}

【问题讨论】:

  • 您可以使用MF的Color Converter DSP docs.microsoft.com/en-us/windows/win32/medfound/colorconverter将YUY2转换为RGB24
  • @SimonMourier 你有用 C# 或 C++ 进行颜色转换器的示例吗?任何帮助将不胜感激。
  • 就像许多 MF 转换一样,您使用 ProcessInput/ProcessOutput,可能在一个循环中,具体取决于上下文。这是伪 C++ 代码:pastebin.com/raw/QQsEnqGV 它使用视频处理器 MFT,但想法相同。启动所有内容后,您必须推送和完整的样本/帧
  • 感谢@SimonMourier,我按照您的建议编写了 MFTransform,但现在我无法将输出缓冲区覆盖到位图源(我正在使用 C# 在 WPF 中实现整个事情)“System.NotSupportedException:'找不到适合完成此操作的成像组件。'
  • @SimonMourier 问题已修复。将媒体类型转换为 RGB24,然后将输出缓冲区转换为可写位图。

标签: c# ms-media-foundation color-space format-conversion


【解决方案1】:

我认为您可以使用媒体基础转换在类型之间进行转换。您可以通过 snarfle 参考来自 MF.net 的示例 enter link description here

【讨论】:

  • 除了写MFT还有其他选择吗?喜欢link
【解决方案2】:

您有多种转换帧的选项。

  1. 在您的 CPU 上。出于明显的原因,我不建议这样做,但如果图像预览不是您的主要功能,您可以摆脱它。像您一样提取缓冲区并手动转换数据数组,最好使用数组操作。
  2. 在硬件上。我有两个选择。第一个是OpenGL。将像素缓冲区分配给 OpenGL 中的缓冲区,并使用着色器将像素从 yuy2 转换为 RGB。为此,请使用 yuy2 规范。
  3. 硬件上的另一个选项是使用 MFT。我真的不知道你为什么不想这样做;它很快。我看到你在 C# 中实现这个,这是一个很大的挑战,但我以前做过,证明它是可能的。如果您愿意,我可以添加一个小代码示例,但我建议使用文档来解决这个问题。关键是配置转换,然后启动转换(将管道设置为以帧为单位),然后将读取到的样本中的缓冲区通过管道传输到转换中,然后从转换中提取结果。

我会在您的场景中推荐 MFT。也许尝试设置 DirectX 或 OpenGL 进行显示;对于更高的分辨率,您使用 BitmapSources 的解决方案可能会很慢。

【讨论】:

  • 感谢分享选项。我正在使用 C# 在 WPF 中编写应用程序。我也一定会尝试 MFTrasform。如果您能分享一些代码示例,那就太好了。
  • 问题已解决。我写了媒体转换来转换媒体类型。
  • 很高兴听到!不要忘记分配答案,或者自己回答问题。
猜你喜欢
  • 1970-01-01
  • 2011-01-02
  • 1970-01-01
  • 2012-04-16
  • 2019-07-15
  • 1970-01-01
  • 2011-10-23
  • 2021-03-02
  • 2017-10-24
相关资源
最近更新 更多