summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Kiagiadakis <george.kiagiadakis@collabora.com>2017-07-27 17:21:48 +0300
committerSebastian Dröge <sebastian@centricular.com>2017-08-17 13:35:34 +0300
commit4abc746fcdf76a1ade14c30e06be778f3fff29a2 (patch)
tree746c47f2b14924064f49f7e8327fa1d2cd980988
parent3c3c1d3e205a397f744c46bd3a4f97acad71deb5 (diff)
downloadgstreamer-plugins-good-4abc746fcdf76a1ade14c30e06be778f3fff29a2.tar.gz
vpxenc: discard frames that have been dropped by libvpx
This fixes a memory leak. When dropframe-threshold has been set, libvpx may output less frames than the input ones, which causes some GstVideoCodecFrames to queue up in GstVideoEncoder's internal frame queue with no chance of ever being all released. And because the frames keep references to the input buffers, the input buffer pool keeps allocating new buffers and memory usage grows very fast. For example the following pipeline's memory usage grows at a rate of about 1GB per minute! videotestsrc ! capsfilter caps=video/x-raw,width=1920,height=1080,framerate=30/1,format=I420 ! \ vp8enc target-bitrate=1000000 end-usage=cbr dropframe-threshold=95 ! fakesink https://bugzilla.gnome.org/show_bug.cgi?id=783086
-rw-r--r--ext/vpx/gstvpxenc.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/ext/vpx/gstvpxenc.c b/ext/vpx/gstvpxenc.c
index 003d4640f..1fa2cccf3 100644
--- a/ext/vpx/gstvpxenc.c
+++ b/ext/vpx/gstvpxenc.c
@@ -1668,6 +1668,7 @@ gst_vpx_enc_process (GstVPXEnc * encoder)
GstVideoCodecFrame *frame;
GstFlowReturn ret = GST_FLOW_OK;
GstVPXEncClass *vpx_enc_class;
+ vpx_codec_pts_t pts;
video_encoder = GST_VIDEO_ENCODER (encoder);
vpx_enc_class = GST_VPX_ENC_GET_CLASS (encoder);
@@ -1707,7 +1708,21 @@ gst_vpx_enc_process (GstVPXEnc * encoder)
}
invisible = (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE) != 0;
- frame = gst_video_encoder_get_oldest_frame (video_encoder);
+
+ /* discard older frames that were dropped by libvpx */
+ frame = NULL;
+ do {
+ if (frame)
+ gst_video_encoder_finish_frame (video_encoder, frame);
+ frame = gst_video_encoder_get_oldest_frame (video_encoder);
+ pts =
+ gst_util_uint64_scale (frame->pts,
+ encoder->cfg.g_timebase.den,
+ encoder->cfg.g_timebase.num * (GstClockTime) GST_SECOND);
+ GST_TRACE_OBJECT (encoder, "vpx pts: %" G_GINT64_FORMAT
+ ", gst frame pts: %" G_GINT64_FORMAT, pkt->data.frame.pts, pts);
+ } while (pkt->data.frame.pts > pts);
+
g_assert (frame != NULL);
if ((pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0)
GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);