Skip to content

Commit 0654fa8

Browse files
author
Clement Champetier
committed
Frame: remove method to ref/unref an other frame
* 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.
1 parent 6954832 commit 0654fa8

File tree

6 files changed

+10
-55
lines changed

6 files changed

+10
-55
lines changed

src/AvTranscoder/data/decoded/Frame.cpp

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,16 @@ Frame::Frame()
1414
Frame::Frame(const Frame& otherFrame)
1515
: _frame(NULL)
1616
{
17-
// allocate frame
1817
allocateAVFrame();
19-
// check if the frame could be a valid video/audio frame
20-
if(otherFrame.getAVFrame().format == -1)
21-
return;
22-
// reference the other frame
23-
refFrame(otherFrame);
18+
copyProperties(otherFrame);
19+
copyData(otherFrame);
2420
}
2521

2622
void Frame::operator=(const Frame& otherFrame)
2723
{
28-
// check if the frame could be a valid video/audio frame
29-
if(otherFrame.getAVFrame().format == -1)
30-
return;
31-
// reference the other frame
32-
refFrame(otherFrame);
24+
allocateAVFrame();
25+
copyProperties(otherFrame);
26+
copyData(otherFrame);
3327
}
3428

3529
Frame::~Frame()
@@ -56,25 +50,6 @@ void Frame::copyProperties(const Frame& otherFrame)
5650
av_frame_copy_props(_frame, &otherFrame.getAVFrame());
5751
}
5852

59-
bool Frame::isRefCounted() const
60-
{
61-
return _frame->buf[0];
62-
}
63-
64-
void Frame::refFrame(const Frame& otherFrame)
65-
{
66-
const int ret = av_frame_ref(_frame, &otherFrame.getAVFrame());
67-
if(ret < 0)
68-
{
69-
throw std::ios_base::failure("Unable to reference other frame: " + getDescriptionFromErrorCode(ret));
70-
}
71-
}
72-
73-
void Frame::unrefFrame()
74-
{
75-
av_frame_unref(_frame);
76-
}
77-
7853
void Frame::allocateAVFrame()
7954
{
8055
#if LIBAVCODEC_VERSION_MAJOR > 54

src/AvTranscoder/data/decoded/Frame.hpp

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class AvExport Frame
2323
Frame();
2424

2525
//@{
26-
// @brief Copy properties and reference data of the other frame.
26+
// @brief Allocate a new frame that references the same data as the given frame.
2727
Frame(const Frame& otherFrame);
2828
void operator=(const Frame& otherFrame);
2929
//@}
@@ -64,23 +64,6 @@ class AvExport Frame
6464
*/
6565
void copyProperties(const Frame& otherFrame);
6666

67-
/**
68-
* @brief If the data buffer of the frame refers to data allocated by an other frame.
69-
*/
70-
bool isRefCounted() const;
71-
72-
/**
73-
* @brief Copy frame properties and create a new reference to data of the given frame.
74-
* @warning This method allocates new data that will be freed by calling clear method or the destructor of the referenced frame.
75-
* @see clear
76-
*/
77-
void refFrame(const Frame& otherFrame);
78-
79-
/**
80-
* @brief Unreference all the buffers referenced by frame and reset the frame fields.
81-
*/
82-
void unrefFrame();
83-
8467
/**
8568
* @return If it corresponds to a valid audio frame.
8669
* @see AudioFrame

src/AvTranscoder/decoder/AudioGenerator.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ bool AudioGenerator::decodeNextFrame(Frame& frameBuffer)
2525
if(! frameBuffer.isAudioFrame())
2626
{
2727
LOG_WARN("The given frame to put data is not a valid audio frame: try to reallocate it.")
28-
frameBuffer.unrefFrame();
28+
static_cast<AudioFrame&>(frameBuffer).freeAVSample();
2929
static_cast<AudioFrame&>(frameBuffer).allocateAVSample(_frameDesc);
3030
}
3131

@@ -50,7 +50,7 @@ bool AudioGenerator::decodeNextFrame(Frame& frameBuffer)
5050
_silent->setNbSamplesPerChannel(frameBuffer.getAVFrame().nb_samples);
5151
}
5252
LOG_DEBUG("Copy data of the silence when decode next frame")
53-
frameBuffer.refFrame(*_silent);
53+
frameBuffer.copyData(*_silent);
5454
}
5555
// Take audio frame from _inputFrame
5656
else

src/AvTranscoder/decoder/VideoGenerator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ bool VideoGenerator::decodeNextFrame(Frame& frameBuffer)
2525
if(! frameBuffer.isVideoFrame())
2626
{
2727
LOG_WARN("The given frame to put data is not a valid video frame: try to reallocate it.")
28-
frameBuffer.unrefFrame();
28+
static_cast<VideoFrame&>(frameBuffer).freeAVPicture();
2929
static_cast<VideoFrame&>(frameBuffer).allocateAVPicture(_frameDesc);
3030
}
3131

src/AvTranscoder/filter/FilterGraph.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ void FilterGraph::process(const std::vector<Frame*>& inputs, Frame& output)
4040
if(!hasFilters())
4141
{
4242
LOG_DEBUG("No filter to process: reference first input frame to the given output.")
43-
output.unrefFrame();
44-
output.refFrame(*inputs.at(0));
43+
output.copyData(*inputs.at(0));
4544
return;
4645
}
4746

src/AvTranscoder/transcoder/StreamTranscoder.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -550,8 +550,6 @@ bool StreamTranscoder::processTranscode()
550550
LOG_DEBUG("Convert")
551551
_transform->convert(*_filteredData, *_transformedData);
552552

553-
_filteredData->unrefFrame();
554-
555553
LOG_DEBUG("Encode")
556554
_outputEncoder->encodeFrame(*_transformedData, data);
557555
}

0 commit comments

Comments
 (0)