Out of memory errors with the Windows Media Format SDK
Over the last few years I’ve worked with a number of engineers that have reported out of memory errors when encoding high definition (HD) video using the Windows Media Format SDK. This issue typically only occurs on 32 bit systems. As we know on a 32 bit Windows OS the maximum memory that your application can allocate is 2 GB. If we try to allocate more than this we get an out of memory error. Out of memory error can also occur because of heap fragmentation. I’ll go into heap fragmentation in detail below.
The Format SDK will use up to the available memory. Internally the Format SDK creates its own heaps. It carefully monitors the memory usage of its heaps. This careful management of its internal heaps should prevent us from ever reaching the 2 GB limit. We might get close but we should never go over. Unfortunately it’s not a perfect world.
Most encoding applications tend to be rather large by their very nature. These large and complex video encoding and editing applications host the format SDK. With the main footprint of the encoding application taking up in the neighborhood of 500 MB to begin with, it’s easy to see how we could quickly hit the 2 GB limit. The Format SDK doesn’t manage the other heaps in the system such as the CRT heap. Because of this the other heaps grow and shrink dynamically. The Format SDK checks to see how much memory is available before it starts encoding. Allocates the heaps and then starts the encoding process.
When dealing with HD video, the amount of memory that must be allocated is substantial. Most people don’t realize that due to the “look ahead, look behind” nature of the VC 1 codec, more than one frame of data must be held in memory at a time. Depending on the encoding settings we can sometimes hold seconds of data in memory. Keep in mind that this is uncompressed data in addition to compressed data. As I’m sure you are aware an uncompressed HD video frame is on the order of 8 MB or more. If we have 5 seconds of cached data at 30 frames per second we’re looking at 1.2 GB. If our application footprint is already at 500 MB we only have 200 MB to work with. This doesn’t offer much breathing room. Factor in heap fragmentation and we start seeing out of memory errors.
Heap fragmentation typically occurs when the heap receives a large number of mixed allocations (large and small). If we then release most of the small allocations but hang on to the large ones things get messy quickly. If we make a request for a really large chunk of memory when the heap is fragmented we can get an out of memory error. This happens because when we request a block of memory the block must be located in a contiguous address range. Unlike the disk subsystem that can write a little bit of the file here and a bit more over there. The memory subsystem requires that we have a contiguous block. So in this case we may be getting out of memory errors but we may see that we haven’t hit the 2 GB limit. The heap manager will eventually come along and compact the heap restoring all of the fragmented segments. Unfortunately the heap compaction process is very processor / memory intensive. Because of this we want to compact the heap as infrequently as possible. If the CPU is under stress, typical when encoding HD video, the OS will not compact the heap until the CPU usage comes down.
Combine all of these contributing factors and you have a recipe for out of memory errors. Luckily there are some tricks you can use to minimize the effects. First try decreasing the profile buffer size to around 1 second. Next try decreasing the key frame interval to around 2 to 3 seconds. You can consider changing the decoder complexity to “simple”. Finally you can try converting all of the standard heaps in the application to low fragmentation heaps. These are just recommendations. Depending on your particular environment you may need to combine one or more of these suggestons before getting the desired effect. Unfortunately I have seen certain scenarios where none of these solutions were completely successful.
Luckily there are two sure fire solutions that will always work. First and foremost, move to a 64 bit version of the operating system and compile your application as 64 bit and large address aware. This will allow the Format SDK to take advantage of the larger address space and you should be able to avoid any out of memory errors related to the 2GB limit. If you can’t move to 64 bit you can create a separate EXE (maybe an out of process COM server) and run the Format SDK encoding from there. Make sure that you don’t do anything else from this separate process other than encoding with the Format SDK and you should be good to go.