Medialooks' SDKs are based on the Components Object Model (COM) technology. Except for advantages, such as multiple programming languages, there are a few things to take care of. One of them is correct redistribution, and another one is releasing of objects.
High-level frameworks, like .NET, have garbage collectors that take care about memory releasing and let your coding be nice and easy. But when it wraps the COM objects like our SDKs it can play a bad trick. The unneeded .NET object can contain just a small link to the COM object, so garbage collector considers it lightweight garbage and postpones memory releasing. But the linked COM object can be really huge, so before garbage collector decides to erase it you may lose a lot of memory. To avoid this situation don't trust the garbage collectors and release all SDK objects manually.
Here are the situations you need to remember about.
Release the main SDK object that you have created and does not need any more
For example:
A temporary MFile object that you've created for service needs.
// Crearte MFile object for temporary needs MFileClass objTemporaryFile = new MFileClass(); // ... // play around with MFile object // ... // Close unneeded MFile object objTemporaryFile.ObjectClose(); // Release it to free the memory System.Runtime.InteropServices.Marshal.ReleaseComObject(objTemporaryFile); runby_bm_b24wcqadm A temporary MLive object that you have used to configure the source of MPlaylist or MMixer
A temporary MLive object that you have used to configure the source of MPlaylist or MMixer
// Create MLive class that will be added as a source to MPlaylist MLiveClass objLive = new MLiveClass(); //... configure MLive object ... // Add MLive object to the playlist MPLATFORMLib.MItem myItem; int index = -1; m_objPlaylist.PlaylistAdd(objLive, "", "", ref index, out myItem); // Release MLive object as we don't need it anymore. System.Runtime.InteropServices.Marshal.ReleaseComObject(objLive); // Release returned MItem object. System.Runtime.InteropServices.Marshal.ReleaseComObject(myItem);
Release SDK objects, returned by SDK methods
For example:
When you add a file to the playlist, it returns the object with a pointer to the newly created object.
Don't forget to release it.
Note: don't close this object as this operation changes its state and it can cause problems for the parent playlist.
// Add new item to the playlist int nIndex = -1; MItem pFile; m_objPlaylist.PlaylistAdd(null, @"c:/MyFile.avi", "", ref nIndex, out pFile); // Release the returned object System.Runtime.InteropServices.Marshal.ReleaseComObject(pFile);
When you get an object with Get method, like PlaylistGetByIndex
Don't forget to release it once you're done.
// Get a playlist item string myItemPath; Double myItemOffset; MPLATFORMLib.MItem myPlaylistItem; m_objPlaylist.PlaylistGetByIndex(0, out myItemOffset, out myItemPath, out myPlaylistItem); // ... // play around with playlist item // ... // Release playlist item when you don't need it anymore System.Runtime.InteropServices.Marshal.ReleaseComObject(myPlaylistItem);
Use safe events and release the objects that you get on events
That's the most important point as the event has risen on each frame it can create tons of unreleased objects within a couple of minutes. To be sure that there is no objects leak you should use safe events (OnFrameSafe instead of OnFrame) and release objects (frames and event objects) that you get on events.
// Use safe event void m_objWriter_OnFrameSafe(string bsChannelID, object pMFrame) { // ... play around with frame ... // Don't forget to release frame object! System.Runtime.InteropServices.Marshal.ReleaseComObject(pMFrame); } // Use safe event. void m_objPlaylist_OnEventSafe(string bsChannelID, string bsEventName, string bsEventParam, object pEventObject) { //... do some event stuff... // Don't forget to release event object! System.Runtime.InteropServices.Marshal.ReleaseComObject(pEventObject); }
Be sure that you release the SDK objects inside your .NET wrapper objects
The tricky thing is that if you'll call the release method in your custom object's destructor, it still will be called when the garbage collector decides to destruct it. That means that you still rely on garbage collector's intelligence and may have some memory load problems.
So to be absolutely sure that you release the SDK object manually we recommend to release it not in a destructor, but in a custom method that you will call to release the objects.
Here is the example of wrapper class:
class MFileWrapper { private MPLATFORMLib.MFileClass m_objMFile; // Just making sure that m_objMFile will be released // when garbage collector destroys my MFileWrapper class ~MFileWrapper() { ReleaseInternalCom(); } // I do not trust garbage collector, so I will call this // method to release the SDK objects manually public void ReleaseInternalCom() { if (m_objMFile != null) { // Close MFile object m_objMFile.ObjectClose(); // Release COM object System.Runtime.InteropServices.Marshal.ReleaseComObject(m_objMFile); m_objMFile = null; } } // ... // some other class code here // ... }
You should release it:
When you don't need it anymore
// Here is my new file wrapper MFileWrapper fileWrapper = new MFileWrapper(); // ... // playing around with it // ... // Release it when you don't need it anymore if (fileWrapper != null) { fileWrapper.ReleaseInternalCom(); }
When you make the assignment.
The COM object can remain when you make assign operation. So we recommend you to release the object manually to be sure that there are no garbage COM objects in memory.
// Here is my new file wrapper MFileWrapper fileWrapper = new MFileWrapper(); // ... // playing around with it // ... // I want to make an assignment, // so I will call the release method to be sure // that no COM objects will remain in memory if (fileWrapper != null) { fileWrapper.ReleaseInternalCom(); } // now I can make assignment being sure that my memory is free fileWrapper = myCachedFileWrapper;
Multiple object usage
If you are going to use create SDK objects multiple times don't forget to call
MPlatform
(m_obj as IMObject).ObjectClose()
The common method for close object - can be used for close any object
MFormats
(m_obj as IMFObject).MFClose();
The common method for close object - can be used for close any object e.g. instead ReaderClose, DeviceClose, SpltterClose etc.