C# WMEncoder在一次迭代后抛出OutOfMemoryException
我正在使用WMEncoder进行屏幕录制。C# WMEncoder在一次迭代后抛出OutOfMemoryException,c#,.net,out-of-memory,encoder,windows-media-encoder,C#,.net,Out Of Memory,Encoder,Windows Media Encoder,我正在使用WMEncoder进行屏幕录制。 第一次,一切正常, 但是在第二次Start()方法将我抛出OutOfMemoryException: System.OutOfMemoryException was caught HResult=-2147024882 Message=Not enough storage is available to complete this operation. 我的代码如下所示,它位于.Net4: // Initialize encoder and
第一次,一切正常,
但是在第二次
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()
{
//从WMEncoder对象创建源组集合对象。
srcGrpColl=mEncoder.SourceGroupCollection;
//将名为SG1的源组添加到集合中。
//为每种类型的多媒体内容创建源对象
//在源组中。
srcGrp=(IWMEncSourceGroup2)srcGrpColl.Add(“SG_1”);
srcVideo=(IWMEncVideoSource2)srcGrp.AddSource(WMENC\u SOURCE\u TYPE.WMENC\u VIDEO);
SetInput(“ScreenCap://ScreenCapture1”,“”,“”);
//从WMEncoder对象创建配置文件集合对象。
mEncoder.ProfileCollection.ProfileDirectory=Path.GetDirectoryName(Assembly.getExecutionGassembly().Location);
mEncoder.ProfileCollection.Refresh();
proColl=mEncoder.ProfileCollection;
//创建纵断面对象
IEnumerator profEnum=proColl.GetEnumerator();
while(profEnum.MoveNext())
{
profile=(IWMEncProfile)profEnum.Current;
如果(profile.Name==“屏幕录制”)
{
//负荷剖面
newProfile=新的WMEncProfile2();
newProfile.LoadFromIWMProfile(配置文件);
受众=新建配置文件。获取受众(0);
受众.set_VideoFPS(0,paramMaps.fpsMapping[fpsKey]*1000);
受众。设置视频关键帧位置(0,关键帧长度*1000);
设置视频宽度(0,Screen.PrimaryScreen.Bounds.Width*paramMaps.imageQualityMapping[qualityRatioKey]/100);
受众.设置视频高度(0,Screen.PrimaryScreen.Bounds.Height*paramMaps.imageQualityMapping[qualityRatioKey]/100);
//将配置文件语言设置为客户端计算机的区域设置。
//当以这种方式进行记录时,从数据库中提取时,它将采用服务器的区域设置。
//这使我们能够知道文件合并应该使用哪种语言环境。
//我们发现,当配置文件设置为与用户的区域设置相同的语言时,录制
//具有“灵活”的语言定义。
int langCount=newProfile.get_LanguageCount(WMENC_SOURCE_TYPE.WMENC_VIDEO,0);
//从配置文件中删除所有现有的语言定义
对于(int i=0;i
微软显然不再支持WMEncoder。我建议研究一下表达式编码器,它使屏幕截图变得非常容易。而且它还为您省去了整理和处理COM的麻烦。您是否有机会检查它是否真的内存不足?例如在Win32
进程中达到虚拟地址限制。作为猜测,编码器可能有内部引用,并且不会立即被破坏,从而保持资源的稳定。性能监视器应该向您展示这个。谢谢@RomanR。我运行了Performance Monitor,但没有发现任何问题或故障,我能做什么?请您演示如何使用SetRecordingParams
和其他相关代码,以便我们可以复制它并自己重新处理问题,ta。@Jeremythonpson我添加了它,但它会减慢我的进程,因为Silverlight无法读取它的输出(或任何其他非windows media player的播放器)所以我需要转换,这需要时间。我自己从未尝试过,但之前提供的编码器页面明确提到了silverlight支持。我可以告诉你,ee4屏幕捕获输出上没有SL支持。很抱歉,这对你没有帮助。反正我明天会快速查看,因为我刚刚完成了一个屏幕捕获项目使用表达式。我对SL的了解是0,所以我测试输出兼容性的能力不是很强。这个链接似乎暗示在表达式中使用VC1预设将产生可用的内容。我有一个很小的测试文件(256K)可供测试。
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;
}