Releasing the SDK objects properly to avoid possible memory overflow

Medialooks' SDKs are based on a the Components Object Model (COM) technology. Except of 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 objects releasing.

A high level frameworks, like .NET, have a 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 SDK 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 a light weight garbage and postpone memory releasing. But the linked COM object can be really huge, so before garbage collector decides  to erase it you may lost 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: 

1) Release the main SDK object that you have created and does not need anymore. 

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);

2) Release SDK objects, returned by SDK methods.

For example:

When you add a file to the playlist, it returns the object with pointer to the newly created object. 
Don't forget to release it.  
Note: don't close this object as  this operation changes it's 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 any 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);

3) Use safe events and release the objects that you get on events.
 
That's the most important point as the event is risen on each frame it can create a 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); 
}

4) 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;