System.OutOfMemoryException
- From: "daveg" <dave_g_work@xxxxxxxxxxx>
- Date: 6 Sep 2006 09:21:40 -0700
Hi
I'm using the WMEncoder with C#. And it appears to be causing this
exception. Can any body help?
The encoder runs as part of a service processing encodings required.
For every encoding a new instance of the encoder is used (WmaEncoder
class below). This is because any error caused within the encoder was
found to throw subsequent errors when processing new encodings through
the same instance of WMEncoder.
I have proved that all the .net managed objects are being garbage
collected correctly i.e. there is no memory loss from my code. So can
only assume the WMEncoder is not being tidied correctly. Is there a
better way of implementing the WMEncoder or is it just bad at loosing
memory?
My implementation is copied in below.
A single instance of the class is created for each encoding call.
Thanks in advance,
Dave
internal class WmaEncoder
{
private Hashtable _profiles;
private WMEncoder _encoder;
private int _errorCode = 0;
private ManualResetEvent _completionSignal;
public WmaEncoder(string profilePath)
{
if (profilePath == null) throw new
ArgumentNullException("profilePath");
_profiles = new Hashtable();
foreach (FileInfo file in new
DirectoryInfo(profilePath).GetFiles("*.prx"))
{
WMEncProfile2 profile = new WMEncProfile2();
profile.LoadFromFile(file.FullName);
_profiles.Add(Path.GetFileNameWithoutExtension(file.Name),
profile);
}
_encoder = new WMEncoder();
_encoder.OnStateChange += new
_IWMEncoderEvents_OnStateChangeEventHandler(OnStateChange);
_encoder.OnError += new
_IWMEncoderEvents_OnErrorEventHandler(OnError);
_completionSignal = new ManualResetEvent(false);
}
/// <summary>
///
/// </summary>
/// <param name="sourceFile">The source file to encode from</param>
/// <param name="outputFolder">The folder to drop the created file
into</param>
/// <param name="format">The required WMA codec/bit rate etc</param>
/// <param name="start">The offset to create the clip from (in
milliseconds)</param>
/// <param name="duration">The duration of the clip (in
milliseconds)</param>
/// <returns>The created file</returns>
/// <exception cref="WmaEncoderException">Thrown if there was an
error with the encoding request, but subsequent encodings should still
be attempted.</exception>
public FileInfo Encode(FileInfo sourceFile,
DirectoryInfo outputFolder,
WmaFormat format,
int start,
int duration,
string fileExt,
ref int actualDuration)
{
if (sourceFile == null) throw new
ArgumentNullException("sourceFile");
if (outputFolder == null) throw new
ArgumentNullException("outputFolder");
if (fileExt == null) throw new ArgumentNullException("fileExt");
if (outputFolder.Exists == false) outputFolder.Create();
_encoder.Reset();
_errorCode = 0;
_completionSignal.Reset();
IWMEncSourceGroup srcGrp =
_encoder.SourceGroupCollection.Add("SG1");
// Retrieve the profile matching the requested format
if (_profiles.ContainsKey(format.ToString()))
{
srcGrp.set_Profile(_profiles[format.ToString()]);
}
else
{
throw new WmaEncoderException("No profile could be loaded for the
format: " + format.ToString());
}
IWMEncAudioSource srcAud =
(IWMEncAudioSource)srcGrp.AddSource(WMENC_SOURCE_TYPE.WMENC_AUDIO);
srcAud.SetInput(sourceFile.FullName, "", "");
if (format.ToString().EndsWith("Vbr"))
{
srcAud.PreProcessPass = 1;
}
else
{
srcAud.PreProcessPass = 0;
}
// Output file
string outputFile = Path.Combine(outputFolder.FullName,
Guid.NewGuid().ToString() + "." + fileExt);
IWMEncFile2 file = (IWMEncFile2)_encoder.File;
file.LocalFileName = outputFile;
try
{
_encoder.PrepareToEncode(true);
// Get the length (in milliseconds) of the song
// NB. We can only read this property after the call to
PrepareToEncode
int songLength = srcAud.Duration;
// Do we want a clip instead of the full track?
if (start > 0 || duration > 0)
{
Utility.CalculateClip(ref start, ref duration,
songLength);
if (start > 0) srcAud.MarkIn = start;
if (duration > 0 && duration < songLength)
srcAud.MarkOut = start + duration;
}
// Calculate the actual duration of the file we are
about to create.
// We want this in seconds and we will pass it out
through the ref parameter
if (srcAud.MarkOut > 0)
{
actualDuration = (srcAud.MarkOut - srcAud.MarkIn) /
1000;
}
else
{
actualDuration = (songLength - srcAud.MarkIn) /
1000;
}
// The call to start is asynchronous
// Wait for the encoding to finish
_encoder.Start();
_completionSignal.WaitOne();
if (_errorCode != 0)
{
try
{
// Found this was necessary otherwise the
encoder keeps a lock on the source file
_encoder.Reset();
}
catch
{
// Sometimes the Reset call fails because of
the original error that has occured.
// We will swallow this exception otherwise it
will obscure the root cause.
}
throw new
WmaEncoderException(WmaEncoderException.BuildExceptionMessage(_errorCode));
}
}
finally
{
// Found this was necessary otherwise the encoder keeps
a lock on the source file
_encoder.Reset();
//required to ensure wmaencoder object is released
_encoder.OnStateChange -= new
_IWMEncoderEvents_OnStateChangeEventHandler(OnStateChange);
_encoder.OnError -= new
_IWMEncoderEvents_OnErrorEventHandler(OnError);
}
return new FileInfo(outputFile);
}
private void OnError(int errorCode)
{
_errorCode = errorCode;
_completionSignal.Set();
}
private void OnStateChange(WMENC_ENCODER_STATE enumState)
{
if (enumState == WMENC_ENCODER_STATE.WMENC_ENCODER_STOPPED)
{
// The encoding has completed
_completionSignal.Set();
}
}
}
.
- Prev by Date: Switching with Fades and Effects
- Next by Date: Re: Scaling WM Servers
- Previous by thread: Switching with Fades and Effects
- Next by thread: Re: Recording desktop as video stream
- Index(es):
Relevant Pages
|