Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/GStreamer/gst-plugins-good.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2020-10-19 18:23:25 +0300
committerSebastian Dröge <sebastian@centricular.com>2020-10-19 22:04:55 +0300
commitd885cc0f1ad68b60f54ac533e3ef252ff52e9853 (patch)
tree94439d35870e89c335983eabbcfd767e1235f719 /sys
parentbcb3428ed06e59945dc1c6034f6e68c0e9d3a964 (diff)
v4l2codec: Garbage collect old frames if they accumulate because of codec bugs
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/778>
Diffstat (limited to 'sys')
-rw-r--r--sys/v4l2/gstv4l2videodec.c36
-rw-r--r--sys/v4l2/gstv4l2videoenc.c35
2 files changed, 70 insertions, 1 deletions
diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index 4f0ff30c2..89ad3e817 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -472,6 +472,22 @@ gst_v4l2_video_dec_drain (GstVideoDecoder * decoder)
return GST_FLOW_OK;
}
+static gboolean
+check_system_frame_number_too_old (guint32 current, guint32 old)
+{
+ guint32 absdiff = current > old ? current - old : old - current;
+
+ /* More than 100 frames in the past, or current wrapped around */
+ if (absdiff > 100) {
+ /* Wraparound and difference is actually smaller than 100 */
+ if (absdiff > G_MAXUINT32 - 100)
+ return FALSE;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static void
gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
{
@@ -517,11 +533,29 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
GST_LOG_OBJECT (decoder, "Got buffer for frame number %u",
(guint32) (GST_BUFFER_TIMESTAMP (buffer) / GST_SECOND));
- /* FIXME: Add garbage collection for the frames */
frame =
gst_video_decoder_get_frame (decoder,
GST_BUFFER_TIMESTAMP (buffer) / GST_SECOND);
if (frame) {
+ GstVideoCodecFrame *oldest_frame;
+ gboolean warned = FALSE;
+
+ /* Garbage collect old frames in case of codec bugs */
+ while ((oldest_frame = gst_video_decoder_get_oldest_frame (decoder)) &&
+ check_system_frame_number_too_old (frame->system_frame_number,
+ oldest_frame->system_frame_number)) {
+ gst_video_decoder_drop_frame (decoder, oldest_frame);
+ oldest_frame = NULL;
+
+ if (!warned) {
+ g_warning ("%s: Too old frames, bug in decoder -- please file a bug",
+ GST_ELEMENT_NAME (decoder));
+ warned = TRUE;
+ }
+ }
+ if (oldest_frame)
+ gst_video_codec_frame_unref (oldest_frame);
+
frame->output_buffer = buffer;
buffer = NULL;
ret = gst_video_decoder_finish_frame (decoder, frame);
diff --git a/sys/v4l2/gstv4l2videoenc.c b/sys/v4l2/gstv4l2videoenc.c
index 193d1f723..117d1400a 100644
--- a/sys/v4l2/gstv4l2videoenc.c
+++ b/sys/v4l2/gstv4l2videoenc.c
@@ -612,6 +612,22 @@ not_negotiated:
return FALSE;
}
+static gboolean
+check_system_frame_number_too_old (guint32 current, guint32 old)
+{
+ guint32 absdiff = current > old ? current - old : old - current;
+
+ /* More than 100 frames in the past, or current wrapped around */
+ if (absdiff > 100) {
+ /* Wraparound and difference is actually smaller than 100 */
+ if (absdiff > G_MAXUINT32 - 100)
+ return FALSE;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static void
gst_v4l2_video_enc_loop (GstVideoEncoder * encoder)
{
@@ -650,6 +666,25 @@ gst_v4l2_video_enc_loop (GstVideoEncoder * encoder)
GST_BUFFER_TIMESTAMP (buffer) / GST_SECOND);
if (frame) {
+ GstVideoCodecFrame *oldest_frame;
+ gboolean warned = FALSE;
+
+ /* Garbage collect old frames in case of codec bugs */
+ while ((oldest_frame = gst_video_encoder_get_oldest_frame (encoder)) &&
+ check_system_frame_number_too_old (frame->system_frame_number,
+ oldest_frame->system_frame_number)) {
+ gst_video_encoder_finish_frame (encoder, oldest_frame);
+ oldest_frame = NULL;
+
+ if (!warned) {
+ g_warning ("%s: Too old frames, bug in encoder -- please file a bug",
+ GST_ELEMENT_NAME (encoder));
+ warned = TRUE;
+ }
+ }
+ if (oldest_frame)
+ gst_video_codec_frame_unref (oldest_frame);
+
/* At this point, the delta unit buffer flag is already correctly set by
* gst_v4l2_buffer_pool_process. Since gst_video_encoder_finish_frame
* will overwrite it from GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame),