Commit 207f0d15 authored by Guillaume Roguez's avatar Guillaume Roguez

media: fix memory leaks

This patch fixes various memory leaks found with ASAN.
  - av_dict_free wasn't called after av_dict_set
  - avformat_free_context wasn't called
  - safe_by_default: all av_malloc has been replaced by std::vector

Tuleap: #412
Change-Id: Ic47cc87b8ed013e7fac5dea80ea7e7aee96139b7
parent 98a66d40
......@@ -49,13 +49,18 @@ MediaDecoder::~MediaDecoder()
if (decoderCtx_)
avcodec_close(decoderCtx_);
if (inputCtx_ and inputCtx_->nb_streams > 0) {
if (inputCtx_) {
if (inputCtx_->nb_streams > 0) {
#if LIBAVFORMAT_VERSION_CHECK(53, 17, 0, 25, 0)
avformat_close_input(&inputCtx_);
avformat_close_input(&inputCtx_);
#else
av_close_input_file(inputCtx_);
av_close_input_file(inputCtx_);
#endif
}
avformat_free_context(inputCtx_);
}
av_dict_free(&options_);
}
int MediaDecoder::openInput(const DeviceParams& params)
......
......@@ -45,17 +45,17 @@ MediaEncoder::MediaEncoder()
MediaEncoder::~MediaEncoder()
{
if (outputCtx_ and outputCtx_->priv_data)
av_write_trailer(outputCtx_);
if (outputCtx_) {
if (outputCtx_->priv_data)
av_write_trailer(outputCtx_);
if (encoderCtx_)
avcodec_close(encoderCtx_);
if (encoderCtx_)
avcodec_close(encoderCtx_);
av_free(scaledFrameBuffer_);
avformat_free_context(outputCtx_);
}
#if (LIBAVCODEC_VERSION_MAJOR < 54)
av_free(encoderBuffer_);
#endif
av_dict_free(&options_);
}
void MediaEncoder::setDeviceOptions(const DeviceParams& args)
......@@ -235,16 +235,11 @@ MediaEncoder::openOutput(const char *filename,
#if (LIBAVCODEC_VERSION_MAJOR < 54)
encoderBufferSize_ = scaledFrameBufferSize_; // seems to be ok
encoderBuffer_ = (uint8_t*) av_malloc(encoderBufferSize_);
if (!encoderBuffer_)
throw MediaEncoderException("Could not allocate encoder buffer");
encoderBuffer_.reserve(encoderBufferSize_);
#endif
scaledFrameBuffer_ = (uint8_t*) av_malloc(scaledFrameBufferSize_);
if (!scaledFrameBuffer_)
throw MediaEncoderException("Could not allocate scaled frame buffer");
scaledFrame_.setFromMemory(scaledFrameBuffer_, format, width, height);
scaledFrameBuffer_.reserve(scaledFrameBufferSize_);
scaledFrame_.setFromMemory(scaledFrameBuffer_.data(), format, width, height);
}
#endif // RING_VIDEO
}
......@@ -342,7 +337,7 @@ MediaEncoder::encode(VideoFrame& input, bool is_keyframe,
#else
int ret = avcodec_encode_video(encoderCtx_, encoderBuffer_,
int ret = avcodec_encode_video(encoderCtx_, encoderBuffer_.data(),
encoderBufferSize_, frame);
if (ret < 0) {
print_averror("avcodec_encode_video", ret);
......@@ -350,7 +345,7 @@ MediaEncoder::encode(VideoFrame& input, bool is_keyframe,
return ret;
}
pkt.data = encoderBuffer_;
pkt.data = encoderBuffer_.data();
pkt.size = ret;
// rescale pts from encoded video framerate to rtp clock rate
......@@ -389,9 +384,8 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer)
return -1;
}
AudioSample *sample_data = reinterpret_cast<AudioSample*>(av_malloc(needed_bytes));
if (!sample_data)
return -1;
std::vector<AudioSample> samples (needed_bytes / sizeof(AudioSample));
AudioSample* sample_data = samples.data();
AudioSample *offset_ptr = sample_data;
int nb_frames = buffer.frames();
......@@ -408,10 +402,8 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer)
while (nb_frames > 0) {
AVFrame *frame = av_frame_alloc();
if (!frame) {
av_freep(&sample_data);
if (!frame)
return -1;
}
if (encoderCtx_->frame_size)
frame->nb_samples = std::min<int>(nb_frames,
......@@ -439,7 +431,6 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer)
av_strerror(err, errbuf, sizeof(errbuf));
RING_ERR("Couldn't fill audio frame: %s: %d %d", errbuf,
frame->nb_samples, buffer_size);
av_freep(&sample_data);
av_frame_free(&frame);
return -1;
}
......@@ -457,7 +448,6 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer)
if (ret < 0) {
print_averror("avcodec_encode_audio2", ret);
av_free_packet(&pkt);
av_freep(&sample_data);
av_frame_free(&frame);
return ret;
}
......@@ -482,8 +472,6 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer)
av_frame_free(&frame);
}
av_freep(&sample_data);
return 0;
}
......@@ -512,7 +500,7 @@ int MediaEncoder::flush()
RING_ERR("write_frame failed");
}
#else
ret = avcodec_encode_video(encoderCtx_, encoderBuffer_,
ret = avcodec_encode_video(encoderCtx_, encoderBuffer_.data(),
encoderBufferSize_, NULL);
if (ret < 0) {
RING_ERR("avcodec_encode_video failed");
......@@ -520,7 +508,7 @@ int MediaEncoder::flush()
return ret;
}
pkt.data = encoderBuffer_;
pkt.data = encoderBuffer_.data();
pkt.size = ret;
// write the compressed frame
......
......@@ -35,6 +35,7 @@
#include <map>
#include <memory>
#include <string>
#include <vector>
class AVCodecContext;
class AVStream;
......@@ -105,11 +106,11 @@ private:
VideoFrame scaledFrame_;
#endif // RING_VIDEO
uint8_t *scaledFrameBuffer_ = nullptr;
std::vector<uint8_t> scaledFrameBuffer_;
int scaledFrameBufferSize_ = 0;
int streamIndex_ = -1;
#if defined(LIBAVCODEC_VERSION_MAJOR) && (LIBAVCODEC_VERSION_MAJOR < 54)
uint8_t *encoderBuffer_ = nullptr;
std::vector<uint8_t> encoderBuffer_;
int encoderBufferSize_ = 0;
#endif
bool is_muted = false;
......
......@@ -28,15 +28,15 @@ MediaIOHandle::MediaIOHandle(std::size_t buffer_size,
io_readcallback read_cb,
io_writecallback write_cb,
io_seekcallback seek_cb,
void *opaque) : ctx_(0), buf_(0)
void *opaque) : ctx_(0)
{
buf_ = static_cast<unsigned char *>(av_malloc(buffer_size));
ctx_ = avio_alloc_context(buf_, buffer_size, writeable, opaque, read_cb,
buf_.reserve(buffer_size);
ctx_ = avio_alloc_context(buf_.data(), buffer_size, writeable, opaque, read_cb,
write_cb, seek_cb);
ctx_->max_packet_size = buffer_size;
}
MediaIOHandle::~MediaIOHandle() { av_free(ctx_); av_free(buf_); }
MediaIOHandle::~MediaIOHandle() { av_free(ctx_); }
} // namespace ring
......@@ -25,6 +25,7 @@
#include <cstdlib>
#include <cstdint>
#include <vector>
#ifndef AVFORMAT_AVIO_H
class AVIOContext;
......@@ -51,7 +52,7 @@ public:
private:
NON_COPYABLE(MediaIOHandle);
AVIOContext *ctx_;
unsigned char *buf_;
std::vector<uint8_t> buf_ {};
};
} // namespace ring
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment