From d1928b0e596ad9e46f4f77e4ab863ad221e68596 Mon Sep 17 00:00:00 2001
From: Eloi BAIL <eloi.bail@savoirfairelinux.com>
Date: Thu, 5 Nov 2015 11:48:24 -0500
Subject: [PATCH] media: fix memory leak in audio decoder

AVPacket are not freed after use. The solution deals with
allocating AVPacket on the stack and ensuring to free it
calling av_packet_unref.
This fix has also widly deployed on Video for having a unique
method other the code.

Change-Id: I049b29effb4e6748ee2dd12b4c52536c99fef498
Tuleap: #91
---
 src/media/media_decoder.cpp              | 31 +++++++++++++++---------
 src/media/media_decoder.h                |  8 ++----
 src/media/video/video_base.cpp           |  9 -------
 src/media/video/video_base.h             | 13 ----------
 src/media/video/video_input.cpp          |  3 +--
 src/media/video/video_receive_thread.cpp |  3 +--
 6 files changed, 23 insertions(+), 44 deletions(-)

diff --git a/src/media/media_decoder.cpp b/src/media/media_decoder.cpp
index 2cd8a06f22..cadbb23002 100644
--- a/src/media/media_decoder.cpp
+++ b/src/media/media_decoder.cpp
@@ -280,10 +280,11 @@ int MediaDecoder::setupFromVideoData()
 }
 
 MediaDecoder::Status
-MediaDecoder::decode(VideoFrame& result, video::VideoPacket& video_packet)
+MediaDecoder::decode(VideoFrame& result)
 {
-    AVPacket *inpacket = video_packet.get();
-    int ret = av_read_frame(inputCtx_, inpacket);
+    AVPacket inpacket;
+    av_init_packet(&inpacket);
+    int ret = av_read_frame(inputCtx_, &inpacket);
     if (ret == AVERROR(EAGAIN)) {
         return Status::Success;
     } else if (ret == AVERROR_EOF) {
@@ -296,13 +297,18 @@ MediaDecoder::decode(VideoFrame& result, video::VideoPacket& video_packet)
     }
 
     // is this a packet from the video stream?
-    if (inpacket->stream_index != streamIndex_)
+    if (inpacket.stream_index != streamIndex_) {
+        av_packet_unref(&inpacket);
         return Status::Success;
+    }
 
     auto frame = result.pointer();
     int frameFinished = 0;
     int len = avcodec_decode_video2(decoderCtx_, frame,
-                                    &frameFinished, inpacket);
+                                    &frameFinished, &inpacket);
+
+    av_packet_unref(&inpacket);
+
     if (len <= 0)
         return Status::DecodeError;
 
@@ -333,10 +339,7 @@ MediaDecoder::decode(const AudioFrame& decodedFrame)
     const auto frame = decodedFrame.pointer();
 
     AVPacket inpacket;
-    memset(&inpacket, 0, sizeof(inpacket));
     av_init_packet(&inpacket);
-    inpacket.data = NULL;
-    inpacket.size = 0;
 
    int ret = av_read_frame(inputCtx_, &inpacket);
     if (ret == AVERROR(EAGAIN)) {
@@ -351,12 +354,16 @@ MediaDecoder::decode(const AudioFrame& decodedFrame)
     }
 
     // is this a packet from the audio stream?
-    if (inpacket.stream_index != streamIndex_)
+    if (inpacket.stream_index != streamIndex_) {
+        av_packet_unref(&inpacket);
         return Status::Success;
+    }
 
     int frameFinished = 0;
     int len = avcodec_decode_audio4(decoderCtx_, frame,
                                     &frameFinished, &inpacket);
+    av_packet_unref(&inpacket);
+
     if (len <= 0) {
         return Status::DecodeError;
     }
@@ -385,14 +392,14 @@ MediaDecoder::Status
 MediaDecoder::flush(VideoFrame& result)
 {
     AVPacket inpacket;
-    memset(&inpacket, 0, sizeof(inpacket));
     av_init_packet(&inpacket);
-    inpacket.data = NULL;
-    inpacket.size = 0;
 
     int frameFinished = 0;
     auto len = avcodec_decode_video2(decoderCtx_, result.pointer(),
                                     &frameFinished, &inpacket);
+
+    av_packet_unref(&inpacket);
+
     if (len <= 0)
         return Status::DecodeError;
 
diff --git a/src/media/media_decoder.h b/src/media/media_decoder.h
index d473d1f0d3..16dad8250f 100644
--- a/src/media/media_decoder.h
+++ b/src/media/media_decoder.h
@@ -17,9 +17,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
  */
-
-#ifndef __MEDIA_DECODER_H__
-#define __MEDIA_DECODER_H__
+#pragma once
 
 #include "config.h"
 
@@ -79,7 +77,7 @@ class MediaDecoder {
         void setIOContext(MediaIOHandle *ioctx);
 #ifdef RING_VIDEO
         int setupFromVideoData();
-        Status decode(VideoFrame&, video::VideoPacket&);
+        Status decode(VideoFrame&);
         Status flush(VideoFrame&);
  #endif // RING_VIDEO
 
@@ -125,5 +123,3 @@ class MediaDecoder {
 };
 
 } // namespace ring
-
-#endif // __MEDIA_DECODER_H__
diff --git a/src/media/video/video_base.cpp b/src/media/video/video_base.cpp
index 835deb8211..9345bce08d 100644
--- a/src/media/video/video_base.cpp
+++ b/src/media/video/video_base.cpp
@@ -29,15 +29,6 @@
 
 namespace ring { namespace video {
 
-/*=== VideoPacket  ===========================================================*/
-
-VideoPacket::VideoPacket() : packet_(static_cast<AVPacket *>(av_mallocz(sizeof(AVPacket))))
-{
-    av_init_packet(packet_);
-}
-
-VideoPacket::~VideoPacket() { av_free_packet(packet_); av_free(packet_); }
-
 /*=== VideoGenerator =========================================================*/
 
 VideoFrame&
diff --git a/src/media/video/video_base.h b/src/media/video/video_base.h
index 8d694d438f..71c0813286 100644
--- a/src/media/video/video_base.h
+++ b/src/media/video/video_base.h
@@ -121,19 +121,6 @@ public:
 struct VideoFrameActiveWriter: Observable<std::shared_ptr<VideoFrame>> {};
 struct VideoFramePassiveReader: Observer<std::shared_ptr<VideoFrame>> {};
 
-/*=== VideoPacket  ===========================================================*/
-
-class VideoPacket {
-    public:
-        VideoPacket();
-        ~VideoPacket();
-        AVPacket* get() { return packet_; };
-
-    private:
-        NON_COPYABLE(VideoPacket);
-        AVPacket *packet_;
-};
-
 /*=== VideoGenerator =========================================================*/
 
 class VideoGenerator : public VideoFrameActiveWriter
diff --git a/src/media/video/video_input.cpp b/src/media/video/video_input.cpp
index 19355e1301..550cb4a34e 100644
--- a/src/media/video/video_input.cpp
+++ b/src/media/video/video_input.cpp
@@ -108,8 +108,7 @@ bool VideoInput::captureFrame()
     if (not decoder_)
         return false;
 
-    VideoPacket pkt;
-    const auto ret = decoder_->decode(getNewFrame(), pkt);
+    const auto ret = decoder_->decode(getNewFrame());
 
     switch (ret) {
         case MediaDecoder::Status::ReadError:
diff --git a/src/media/video/video_receive_thread.cpp b/src/media/video/video_receive_thread.cpp
index 10d0d54e59..6fe210455e 100644
--- a/src/media/video/video_receive_thread.cpp
+++ b/src/media/video/video_receive_thread.cpp
@@ -155,8 +155,7 @@ void VideoReceiveThread::addIOContext(SocketPair &socketPair)
 
 bool VideoReceiveThread::decodeFrame()
 {
-    VideoPacket pkt;
-    const auto ret = videoDecoder_->decode(getNewFrame(), pkt);
+    const auto ret = videoDecoder_->decode(getNewFrame());
 
     switch (ret) {
         case MediaDecoder::Status::FrameFinished:
-- 
GitLab