From db52a2e2e655a9a06835b91a0b3f1f261c930455 Mon Sep 17 00:00:00 2001 From: Hyunil Date: Wed, 4 Nov 2020 16:47:20 +0900 Subject: [PATCH] rtpv8depay: Add property for waiting until the next keyframe after packet loss [Version] 1.16.2-14 [Issue Type] Improvement If VP8 is not encoded with error resilience enabled then any packet loss causes very bad artefacts when decoding and waiting for the next keyframe instead improves user experience considerably. Patch is got from gstreamr upstream master branch https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/318/diffs?commit_id=f2a3bb7999cc36471849944b5e810f1ca3d57876 Change-Id: I14fa420bca71b8107fd456c6543b6ab4c1831049 Signed-off-by: Hyunil --- gst/rtp/gstrtpvp8depay.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++-- gst/rtp/gstrtpvp8depay.h | 7 +++++ 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/gst/rtp/gstrtpvp8depay.c b/gst/rtp/gstrtpvp8depay.c index 7c0d707..6da17e2 100644 --- a/gst/rtp/gstrtpvp8depay.c +++ b/gst/rtp/gstrtpvp8depay.c @@ -33,6 +33,12 @@ GST_DEBUG_CATEGORY_STATIC (gst_rtp_vp8_depay_debug); #define GST_CAT_DEFAULT gst_rtp_vp8_depay_debug static void gst_rtp_vp8_depay_dispose (GObject * object); +#ifdef TIZEN_FEATURE_GST_UPSTREAM +static void gst_rtp_vp8_depay_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_rtp_vp8_depay_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +#endif static GstBuffer *gst_rtp_vp8_depay_process (GstRTPBaseDepayload * depayload, GstRTPBuffer * rtp); static GstStateChangeReturn gst_rtp_vp8_depay_change_state (GstElement * @@ -57,11 +63,24 @@ GST_STATIC_PAD_TEMPLATE ("sink", "media = (string) \"video\"," "encoding-name = (string) { \"VP8\", \"VP8-DRAFT-IETF-01\" }")); +#ifdef TIZEN_FEATURE_GST_UPSTREAM +#define DEFAULT_WAIT_FOR_KEYFRAME FALSE + +enum +{ + PROP_0, + PROP_WAIT_FOR_KEYFRAME +}; +#endif + static void gst_rtp_vp8_depay_init (GstRtpVP8Depay * self) { self->adapter = gst_adapter_new (); self->started = FALSE; +#ifdef TIZEN_FEATURE_GST_UPSTREAM + self->wait_for_keyframe = DEFAULT_WAIT_FOR_KEYFRAME; +#endif } static void @@ -84,7 +103,16 @@ gst_rtp_vp8_depay_class_init (GstRtpVP8DepayClass * gst_rtp_vp8_depay_class) "Sjoerd Simons "); object_class->dispose = gst_rtp_vp8_depay_dispose; - +#ifdef TIZEN_FEATURE_GST_UPSTREAM + object_class->set_property = gst_rtp_vp8_depay_set_property; + object_class->get_property = gst_rtp_vp8_depay_get_property; + + g_object_class_install_property (object_class, PROP_WAIT_FOR_KEYFRAME, + g_param_spec_boolean ("wait-for-keyframe", "Wait for Keyframe", + "Wait for the next keyframe after packet loss", + DEFAULT_WAIT_FOR_KEYFRAME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +#endif element_class->change_state = gst_rtp_vp8_depay_change_state; depay_class->process_rtp_packet = gst_rtp_vp8_depay_process; @@ -109,6 +137,40 @@ gst_rtp_vp8_depay_dispose (GObject * object) G_OBJECT_CLASS (gst_rtp_vp8_depay_parent_class)->dispose (object); } +#ifdef TIZEN_FEATURE_GST_UPSTREAM +static void +gst_rtp_vp8_depay_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstRtpVP8Depay *self = GST_RTP_VP8_DEPAY (object); + + switch (prop_id) { + case PROP_WAIT_FOR_KEYFRAME: + self->wait_for_keyframe = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_rtp_vp8_depay_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstRtpVP8Depay *self = GST_RTP_VP8_DEPAY (object); + + switch (prop_id) { + case PROP_WAIT_FOR_KEYFRAME: + g_value_set_boolean (value, self->wait_for_keyframe); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} +#endif + static GstBuffer * gst_rtp_vp8_depay_process (GstRTPBaseDepayload * depay, GstRTPBuffer * rtp) { @@ -122,6 +184,10 @@ gst_rtp_vp8_depay_process (GstRTPBaseDepayload * depay, GstRTPBuffer * rtp) GST_LOG_OBJECT (self, "Discontinuity, flushing adapter"); gst_adapter_clear (self->adapter); self->started = FALSE; +#ifdef TIZEN_FEATURE_GST_UPSTREAM + if (self->wait_for_keyframe) + self->waiting_for_keyframe = TRUE; +#endif } size = gst_rtp_buffer_get_payload_len (rtp); @@ -190,7 +256,11 @@ gst_rtp_vp8_depay_process (GstRTPBaseDepayload * depay, GstRTPBuffer * rtp) if ((header[0] & 0x01)) { GST_BUFFER_FLAG_SET (out, GST_BUFFER_FLAG_DELTA_UNIT); +#ifdef TIZEN_FEATURE_GST_UPSTREAM + if (self->waiting_for_keyframe) { +#else if (!self->caps_sent) { +#endif gst_buffer_unref (out); out = NULL; GST_INFO_OBJECT (self, "Dropping inter-frame before intra-frame"); @@ -221,12 +291,16 @@ gst_rtp_vp8_depay_process (GstRTPBaseDepayload * depay, GstRTPBuffer * rtp) gst_pad_set_caps (GST_RTP_BASE_DEPAYLOAD_SRCPAD (depay), srccaps); gst_caps_unref (srccaps); - +#ifndef TIZEN_FEATURE_GST_UPSTREAM self->caps_sent = TRUE; +#endif self->last_width = width; self->last_height = height; self->last_profile = profile; } +#ifdef TIZEN_FEATURE_GST_UPSTREAM + self->waiting_for_keyframe = FALSE; +#endif } return out; @@ -253,7 +327,11 @@ gst_rtp_vp8_depay_change_state (GstElement * element, GstStateChange transition) self->last_profile = -1; self->last_height = -1; self->last_width = -1; +#ifdef TIZEN_FEATURE_GST_UPSTREAM + self->waiting_for_keyframe = TRUE; +#else self->caps_sent = FALSE; +#endif break; default: break; diff --git a/gst/rtp/gstrtpvp8depay.h b/gst/rtp/gstrtpvp8depay.h index 258546a..0dc5c53 100644 --- a/gst/rtp/gstrtpvp8depay.h +++ b/gst/rtp/gstrtpvp8depay.h @@ -54,10 +54,17 @@ struct _GstRtpVP8Depay GstAdapter *adapter; gboolean started; +#ifdef TIZEN_FEATURE_GST_UPSTREAM + gboolean waiting_for_keyframe; +#else gboolean caps_sent; +#endif gint last_profile; gint last_width; gint last_height; +#ifdef TIZEN_FEATURE_GST_UPSTREAM + gboolean wait_for_keyframe; +#endif }; GType gst_rtp_vp8_depay_get_type (void); -- 2.7.4