【问题标题】:WMEncoder throws OutOfMemoryException after one iterationWMEncoder 在一次迭代后抛出 OutOfMemoryException
【发布时间】:2012-06-27 12:26:39
【问题描述】:

我正在使用 WMEncoder 进行屏幕录制。
第一次一切正常,
但在第二次Start() 方法抛出我OutOfMemoryException

System.OutOfMemoryException was caught
  HResult=-2147024882
  Message=Not enough storage is available to complete this operation.

我的代码看起来像这样,它在 .Net4 上:

// Initialize encoder and set recording parameters
mEncoder = new WMEncoder();
SetRecordingParams(); // If it's relevant I can attach this function

// Set the output file.
mEncoder.EnableAutoArchive = true;
mEncoder.AutoIndex = true;
mEncoder.File.LocalFileName = tempRecFile;

// Start the encoding process.
mEncoder.PrepareToEncode(true);
mEncoder.Start();

// If currently recording, stop recording
if (mEncoder != null &&
    mEncoder.RunState != WMENC_ENCODER_STATE.WMENC_ENCODER_STOPPED)
{

    // Stop recording
    mEncoder.Stop();
}

// Releasing Com object
if (mEncoder != null)
{
    Marshal.FinalReleaseComObject(mEncoder);
    mEncoder = null;
}

帮帮我!

更新

 private void SetRecordingParams()
        {
            // Create a source group collection object from the WMEncoder object.
            srcGrpColl = mEncoder.SourceGroupCollection;

            // Add a source group named SG1 to the collection.
            // Create a source object for each type of multimedia content
            // in the source group.
            srcGrp = (IWMEncSourceGroup2)srcGrpColl.Add("SG_1");
            srcVideo = (IWMEncVideoSource2)srcGrp.AddSource(WMENC_SOURCE_TYPE.WMENC_VIDEO);
            srcVideo.SetInput("ScreenCap://ScreenCapture1", "", "");

            // Create a profile collection object from the WMEncoder object.
            mEncoder.ProfileCollection.ProfileDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            mEncoder.ProfileCollection.Refresh();
            proColl = mEncoder.ProfileCollection;

            // Create a profile object
            IEnumerator profEnum = proColl.GetEnumerator();
            while (profEnum.MoveNext())
            {
                profile = (IWMEncProfile)profEnum.Current;
                if (profile.Name == "Screen Recording")
                {
                    // Load profile
                    newProfile = new WMEncProfile2();
                    newProfile.LoadFromIWMProfile(profile);

                    audience = newProfile.get_Audience(0);

                    audience.set_VideoFPS(0, paramMaps.fpsMapping[fpsKey] * 1000);
                    audience.set_VideoKeyFrameDistance(0, keyFrameInt * 1000);
                    audience.set_VideoWidth(0, Screen.PrimaryScreen.Bounds.Width * paramMaps.imageQualityMapping[qualityRatioKey] / 100);
                    audience.set_VideoHeight(0, Screen.PrimaryScreen.Bounds.Height * paramMaps.imageQualityMapping[qualityRatioKey] / 100);

                    // Set profile language to client machine's locale.
                    // When recording is done this way, it will assume server's locale when extracted from the DB.
                    // This enables us to know which locale should be used for the file merge.
                    // We have found that when profile is set to the same language as user's locale, the recording
                    // has a "flexible" language definition.
                    int langCount = newProfile.get_LanguageCount(WMENC_SOURCE_TYPE.WMENC_VIDEO, 0);
                    // Remove all existing language definitions from profile
                    for (int i = 0; i < langCount; i++)
                    {
                        newProfile.RemoveLanguage(WMENC_SOURCE_TYPE.WMENC_VIDEO, 0, newProfile.get_Language(WMENC_SOURCE_TYPE.WMENC_VIDEO, 0, i));
                    }
                    // Add current locale as profile language.
                    int lcid = Thread.CurrentThread.CurrentCulture.LCID;
                    newProfile.AddLanguage(WMENC_SOURCE_TYPE.WMENC_VIDEO, 0, lcid);

                    // Specify this profile object as the profile to use in source group.
                    srcGrp.set_Profile(newProfile);
                }
            }
            mEncoder.VideoComplexity = WMENC_VIDEOCOMPLEXITY.WMENC_COMPLEXITY_LEVEL20;
        }

【问题讨论】:

  • 您是否有机会检查它是否确实内存不足?例如在Win32 进程中达到虚拟地址限制。作为一种猜测 - 编码器可能具有内部引用并且不会立即被破坏以保持对资源的持有。性能监视器应该会向您显示这一点。
  • 感谢@RomanR。我运行了性能监视器,但没有发现任何问题或故障,我该怎么办?
  • 能否请您出示使用SetRecordingParams和其他相关代码,以便我们自己复制和重现问题,ta。
  • @JeremyThompson 我添加它

标签: c# .net out-of-memory encoder windows-media-encoder


【解决方案1】:

微软显然不再支持 WMEncoder。我建议您研究一下表达式编码器,它确实使屏幕捕获非常容易 - http://www.microsoft.com/expression/products/Encoder4_Overview.aspx。它还为您省去了编组和处理 COM 的麻烦。

【讨论】:

  • 但它会减慢我的进程,因为 Silverlight(或任何其他非 Windows 媒体播放器的播放器)无法读取它的输出,所以我需要转换,这需要时间
  • 我自己从未尝试过,但之前提供的编码器页面明确提到了 Silverlight 支持。
  • 我可以告诉你,ee4 截屏输出不支持 SL
  • 很抱歉听到这对您没有帮助。无论如何,我明天会快速浏览一下,因为我刚刚完成了一个使用表达式进行屏幕截图的项目。
  • 我对 SL 的了解是 0,所以我测试输出兼容性的能力不是很好。这个链接msdn.microsoft.com/en-us/library/cc189080(v=vs.95).aspx 似乎暗示在表达式中使用 VC1 预设会产生可用的内容。我有一个很小的测试文件 (256K),可以提供用于测试。
猜你喜欢
  • 2016-04-13
  • 2017-06-15
  • 1970-01-01
  • 1970-01-01
  • 2015-02-28
  • 2014-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多