aviread and mmread memory usage
Show older comments
I want to process images frame by frame using aviread or mmread and then save the processed images as a new movie. I have preallocated the structure array for the frames without memory issues,
D(1:nFrames) = struct('cdata', ones(vidHeight, vidWidth, 3, 'uint8'),'colormap', []);
but as the loop runs aviread and mmread use up all the memory even though they are not storing any new variables (that I can see). When it reaches frame 420 out of 1444 (1024x1024x3 colordata) it fails with:
??? The file could not be read. (Ran out of memory ) Error in ==> mmreader.read at 74 videoFrames = read(getImpl(obj), index);
Why should it run out of memory if the array is completely preallocated and it is only reading one frame at a time?
1 Comment
David Tarkowski
on 11 May 2011
Can you provide more of your code that is causing the problems. Specifically, how are you using mmreader or aviread?
Answers (1)
Walter Roberson
on 10 May 2011
When the entire contents of a structure field are being replaced, MATLAB does not copy the new values in to the existing storage: it unlinks the old storage from that place (returning it to the memory manager if there are no further references to it) and links in the new value array. Thus, even if everything else was going right, it would not be the old memory that was being used. Memory fragmentation permitting, though, any memory returned to the memory manager in this way would be eligible to be allocated within aviread() or mmread() and possibly end up being used in the structure for some later frame.
Now, in this description, notice that I said "returning it to the memory manager if there are no further references to it." You have a problem in that regards: the blocks have many other references to them!
When you assign the same value (the entire structure in this case) to a number of different locations (the array D(1:nFrames)), MATLAB saves on memory and computation by setting each of the destination entries to point to the same value block. Your code generates a single array of 1's, and makes nFrames references to that single array. When it needs to alter an instance that is shared, it unlinks in the destination, reducing the reference count. If you think about that briefly, you will see that your code ends up pre-allocating a small amount of memory, and then to need to allocate more memory for each frame read in.
In short: change your code to
D(1:nFrames) = struct('cdata',[], 'colormap, []);
for K = 1:nFrames
D(K).cdata = zeros(vidHeight,VidWidth,3,'uint8');
end
(Arrays of all zeros can be faster than arrays of all ones.)
If you run out of room in doing this, you would not have had room for all of the frames.
Yeh, this isn't vectorized, but the vectorized versions either end up sharing memory or end up needing temporary memory too large for you to afford.
2 Comments
John
on 10 May 2011
Walter Roberson
on 10 May 2011
VideoReader's read function, http://www.mathworks.com/help/techdoc/ref/videoreader.read.html
VideoWriter's writeVideo function, http://www.mathworks.com/help/techdoc/ref/videowriter.writevideo.html
Note: I have not used these functions myself, and so do not know how much internal buffering they need to do.
Categories
Find more on Read, Write, and Modify Image in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!