[libav-api] AVFrame memory management

Anton Khirnov anton at khirnov.net
Tue Aug 19 21:08:41 CEST 2014


On Tue, 19 Aug 2014 11:44:46 +0200, g kuczera <gkuczera at gmail.com> wrote:
> Hi Boys and Girls,
> This time I was wandering about AVFrame's memory management. In my project,
> I receive frames, which have to be merged (I got them from the Internet).
> 
> I can't operate on the original frame, so I create "copied frames", which
> will be used to perform operations on. The copy operation is the sws_scale
> function usage.
> 
> Here is the sample, in which I merge two cloned frames (the same ones) into
> bigger one in my FramesMerger class.
> 
> void gotFrame(AVFrame* pFrame)
> {
> AVPixelFormat tFrameFormat = static_cast<AVPixelFormat>(pFrame->format);
> AVFrame* tCopiedFrame1 = getPreparedFrame(tFrameFormat, pFrame->width,
> pFrame->height);
> AVFrame* tCopiedFrame2 = getPreparedFrame(tFrameFormat, pFrame->width,
> pFrame->height);
> // if (tCopiedFrame1 && tCopiedFrame2)
> SwsContext* tScaleContext = sws_getContext(pFrame->width, pFrame->height,
> tFrameFormat, pFrame->width, pFrame->height, tFrameFormat, SWS_BILINEAR,
> NULL, NULL, NULL);
> 
> sws_scale(tScaleContext, (const uint8_t* const *)pFrame->data,
> pFrame->linesize, 0, pFrame->height, tCopiedFrame1->data,
> tCopiedFrame1->linesize);
> sws_scale(tScaleContext, (const uint8_t* const *)pFrame->data,
> pFrame->linesize, 0, pFrame->height, tCopiedFrame2->data,
> tCopiedFrame2->linesize);
> 
> tCopiedFrame1->width = pFrame->width;
> tCopiedFrame1->height = pFrame->height;
> tCopiedFrame1->format = tFrameFormat ;
> 
> tCopiedFrame2->width = pFrame->width;
> tCopiedFrame2->height = pFrame->height;
> tCopiedFrame2->format = tFrameFormat ;
> 
> mFramesMerger.addFrame(tCopiedFrame1, 1);
> mFramesMerger.addFrame(tCopiedFrame2, 2);
> 
> AVFrame* tMergedFrame = mFramesMerger.getFrame();
> }
> 
> The getPreparedFrame function looks like this:
> 
> AVFrame* getPreparedFrame(AVPixelFormat pPixelFormat, int pWidth /*= 320*/,
> int pHeight /*= 240*/)
> {
> AVFrame* tFrame = av_frame_alloc();
> 
> if (!tFrame)
> {
> return NULL;
> }
> 
> int tBytesNeeded = avpicture_get_size(pPixelFormat, pWidth, pHeight);
> uint8_t* tBuffer = (uint8_t*)av_malloc(tBytesNeeded * sizeof(uint8_t));
> avpicture_fill((AVPicture*)tFrame, tBuffer, pPixelFormat, pWidth, pHeight);
> 
> return tFrame;
> }
> 
> After all of that I release the added frames in this way:
> 
> 
> avpicture_free((AVPicture*)mFrame);
> av_frame_free(&mFrame);
> mFrame = NULL;
> 
> But when I look at my memory usage (CTRL + SHIFT + ESC in Windows) I can
> see that it's growing fast while the program is running. What do you think
> about releasing the frame? I should also delete the frame data right
> (tBuffer)? How to get access to this field, when I only have pointer to the
> AVFrame? I realize that freeing AVFrame's memory should be proceeded on two
> levels: one deletion of data and one of the frame structure - av_frame_free
> deletes the second one, but how about the raw data?
> 
> Can you "give me a hand" or at least "point a direction"?

If your libav is new enough to contain av_frame_*, then you shouldn't allocate
the buffers manually with avpicture stuff, but use av_frame_get_buffer(). Then
av_frame_free() will automagically free both the data and the frame for you.

-- 
Anton Khirnov


More information about the libav-api mailing list