summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Kiagiadakis <george.kiagiadakis@collabora.com>2017-07-27 14:21:48 (GMT)
committerGeorge Kiagiadakis <george.kiagiadakis@collabora.com>2017-08-11 11:32:37 (GMT)
commit36fc2a747ade50db69221a502d498efa890bf054 (patch)
treee0f5e93bd00ba37c0dc5a25313a06b484e07e0cc
parent5e48e85fb7db4c31b5652c9a002574f2879da191 (diff)
downloadgst-plugins-good-36fc2a747ade50db69221a502d498efa890bf054.tar.gz
gst-plugins-good-36fc2a747ade50db69221a502d498efa890bf054.tar.xz
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 003d464..1fa2ccc 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);