Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
libav: fix memory leak when converting packets to annex-b format
- Loading branch information
John Törnblom
committed
Mar 13, 2013
1 parent
819b8c8
commit 84b2264
Showing
1 changed file
with
4 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84b2264There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I doubt this is correct as you don't check the return value of the call to libav routine. Look at example given in the bug report
84b2264There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect, as in still leaking memory?
84b2264There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No but doing free when it should not and not checking possible errors...
84b2264There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okey, when should the memory be released then?
84b2264There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Read the code at the line I pointed in the bug!
Pointer change can be done without reallocation if I read the ffmpeg.c code correctly in that case 0 is returned in the function call. >0 mean reallocation occured but that does not mean pointer change in all cases (e.g. malloc chunk has free size left after the returned pointer to store more data)
from realloc documentaion : If the area pointed to was moved, a free(ptr) is done => this means it does not always occur and then the pointer in the pkt should be marked as no more valid!
84b2264There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand what you mean.
The only memory that is released at the line you pointed out (avconv.c:943) is the incomming packet (pkt). In tvheadend, the incomming packet is released elsewhere. However, the data allocated by the filter was not released elsewhere, hence the memory leak. This commit will check if the filter allocated new memory and if so, release it.
84b2264There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The right way to know if function reallocated memory is via return value not pointer change. The pointer in the pkt may have become invalid or still be valid depending on the return value. And reading ffmepg.c you will see that pointer change may occur without reallocation.
84b2264There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking at http://www.ffmpeg.org/doxygen/trunk/h264__mp4toannexb__bsf_8c_source.html#l00059 three things can happend:
ret == 0 : no filtering was done --> input == output.
ret > 0 : filter was successful --> input != output. (input untouched, output is new allocated memory, not reallocated from input).
ret < 0 : something wen't wrong (ENOMEM, EINVAL etc) --> input == output (see http://www.ffmpeg.org/doxygen/trunk/bitstream__filter_8c_source.html#l00061)
I'm not sure what you mean by "the pointer in the pkt"). the filter doesn't take AVPacket as input. It takes a const uint8* as input and **uint8_t as output. I think you have missunderstood something.
84b2264There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@EricV I'm no expert on this, but having read the code and looked at the documentation from what I can see the input ptr should never be altered, the output ptr can be either newly allocated (from within the filter and may have been realloc'd several times) or will be set to the input if no filtering is required.
So checking in != out will tell you whether memory has been allocated. However the one thing that does concern me about not checking the return value is on error its possible the out ptr has been assigned but subsequently free'd so we may try to double free it. So @john-tornblom I do think you should at least check the return value for the error condition.
Adam
84b2264There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adamsutton I thinks, the discussion arise because john is looking directly at the instantiation of av_bitstream_filter_filter for the specific use case while I'm looking to generic usage of av_bitstream_filter_filter in the first place.
When I read http://www.ffmpeg.org/doxygen/trunk/ffmpeg_8c_source.html: line 583
int a = av_bitstream_filter_filter(bsfc, avctx, NULL, &new_pkt.data, &new_pkt.size, pkt->data, pkt->size,pkt->flags & AV_PKT_FLAG_KEY);
if(a == 0 && new_pkt.data != pkt->data && new_pkt.destruct)
I think I can say in general that you can have no reallocation and newtr != ptr when using av_bitstream_filter_filter. And I do disagree with the code for that reason. Not sure for this specific filter instantiation (although trying to understand code in a meeting is not easy) but why not writing code that may indeed serve as a template for transcoding to other format?
I do agree reading the code that ptr pointer shall not be altered.
84b2264There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yepp, return value can be used to check for errors. the question is what to do. close the muxer? drop the package? ignore the error and append package as-is? For now, I'll add a warning message and append package as-is.
84b2264There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer to test 0 or non zero instead of the pointer for detecting the need to free as well.
84b2264There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@EricV
I understand that you're looking at it from a general point of view. I think we agree that the original ptr cannot be changed, if it were that would be a gross violation and would be out of scope of what can be checked/handled.
I think that the specific line you're talking about a==0 and new != old, is implying that the return ptr has been set to NULL in the event of no filtering (as opposed to set to the input ptr). And therefore the memory needs copying into the original. Though I might have read that wrong.
The only things I can see that needs changing is:
need to check for error return, in which case the return ptr should be assumed free'd and no further action (to cleanup) need be taken. But that the pkt will need to be ignored.
need to check that new ptr has actually been allocated. Which is something not currently done.
Adam
84b2264There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@EricV it all equates to the same thing really, just diff ways of checking. But I do agree that checking the return value makes sense, given that it can indicate the validity of the return ptr.