-
Notifications
You must be signed in to change notification settings - Fork 50
Fix memory leaks #282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix memory leaks #282
Conversation
Will be used when calling refFrame.
Symmetry with refFrame.
To keep symmetry with allocateAVFrame private method.
* Same behavior as before. * But this call is explicitly mention in the documentation.
* The way to reference other frame in ffmpeg/libav is tricky. For example, if src is not reference counted, new buffers are allocated and the data is copied. And this case leads us to memory leaks in our program! * See the code: https://www.ffmpeg.org/doxygen/2.6/frame_8c_source.html#l00278 * Because we do not reference a lot of frames in our code, to avoid an overhead of complexity this commit removes these methods. * Instead, we copy the data.
* According to the doc, for each new stream added, the user should call avcodec_close and avformat_free_context. * See the doc: https://www.ffmpeg.org/doxygen/3.0/group__lavf__core.html#gadcb0fd3e507d9b58fe78f61f8ad39827
* This is a common case, without filters added. * This avoid a copy of the data of each encoded frame.
Because we are using ffmpeg/libav functions, we should use ffmpeg/libav structures too.
* A data buffer is not allocated by default in the constructor. * Frame is now an abstract class: easier to call allocateData and freeData methods. * Depending on the case, we could manipulate frame with data allocated elsewhere. For example, an empty frame is given to a decoder, which is responsible to allocate and free the data buffers.
* Remove protected method inherited from ITransform. * Add the same series of test for the video and the audio transform.
In that case, the data buffer of the generated data should be allocated manually.
* Solution: keep the original description when the frame was created, and use it to reallocate it when needed. * No need to check and reallocate data in the generators.
Because the common case is to allocate the data at the same time as the frame itself, this commit adds a default parameter to the constructor of Video/Audio frames.
This info can be found from elsewhere, and the method is not so used.
* IFrame is an abstract class. * To keep the naming convention of the project, rename it to IFrame.
* Less code to maintain. * Rename assign methods to assignBuffer and assignValue (to avoid implicite C++ cast and so calling the wrong method).
* The data buffer of the frame should be freed before allocate a new buffer. * The new buffer should be allocated using malloc instead of free, since ffmpeg/libav uses free to deallocate the data. The valgrind error was: "Mismatched free() / delete / delete []".
In a demultiplexing case, the buffer should be allocated by us, but only once (not in the decodeNextFrame method)!
The number of channels and the channel layout is already correctly set by the StreamTranscoder.
In this case, the buffer of decoded data should be manually allocated, and freed when it is the decoder's turn.
* If the buffer of filtered data is too small: reallocate it. * If the buffer of transformed data is too small: reallocate it.
…size No real impact in the process, because we only check that "decodedSize" is not equal to 0. But it is more accurate :)
1 similar comment
…iplexing In case of audio demultiplexing, we allocate the data buffer, so we should not reallocate it when we switch to a generator.
2 similar comments
2 similar comments
@@ -23,7 +23,7 @@ class AvExport Frame | |||
Frame(); | |||
|
|||
//@{ | |||
// @brief Copy properties and reference data of the other frame. | |||
// @brief Allocate a new frame that references the same data as the given frame. |
There 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.
Allocate a new frame that copies the same data as the given frame.
There 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.
This copy constructor has been removed.
@@ -76,9 +79,6 @@ size_t VideoFrame::getSize() const | |||
|
|||
void VideoFrame::allocateData() | |||
{ | |||
if(_dataAllocated) | |||
return; |
There 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.
Removing this, you allow an allocated frame to be reallocated, is that really what you want?
There 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.
Yes. But we can check if this is needed or not... If it is so, it should be ugly!
There 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.
Log a warning is that case: cd2db7b
os << "sample format = " << getSampleFormatName(_desc._sampleFormat); | ||
LOG_ERROR(os.str()) | ||
const std::string formatName = getSampleFormatName(_desc._sampleFormat); | ||
std::stringstream stream; |
There 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.
stream could be a bit confusing in this transcoder context... ;)
There 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.
@@ -49,6 +49,7 @@ class AvExport AudioFrame : public IFrame | |||
*/ | |||
void allocateData(); | |||
void freeData(); | |||
size_t getSize() const; |
There 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.
So, it could have been renamed getDataSize()!
There 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.
* @brief The number of samples of a frame cannot be known before calling avcodec_decode_audio4, | ||
* and can be variable in a same stream. Because we need to allocate some frames without knowing this parameter, | ||
* we access here a default number of samples. | ||
* @note This value depends on the sample rate (excample: 1920 samples at 48kHz). |
There 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.
example
There 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 most important parts of the code which lead to memory leaks were:
allocation of data buffers when decoding (which is the job of the decoder).reference of data buffers of other frames (which can produce copy of data depending on the state of the AVFrame).assignment of external data buffer in the generators.