rtph265depay: Add request-keyframe property
Similar to the H264 depayloader, this property will request a new keyframe when packet loss is detected. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8343>
This commit is contained in:
parent
ca08f4220a
commit
4400caeaef
@ -40,11 +40,13 @@ GST_DEBUG_CATEGORY_STATIC (rtph265depay_debug);
|
||||
#define DEFAULT_STREAM_FORMAT GST_H265_STREAM_FORMAT_BYTESTREAM
|
||||
#define DEFAULT_ACCESS_UNIT FALSE
|
||||
#define DEFAULT_WAIT_FOR_KEYFRAME FALSE
|
||||
#define DEFAULT_REQUEST_KEYFRAME FALSE
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_WAIT_FOR_KEYFRAME
|
||||
PROP_WAIT_FOR_KEYFRAME,
|
||||
PROP_REQUEST_KEYFRAME,
|
||||
};
|
||||
|
||||
|
||||
@ -137,6 +139,9 @@ gst_rtp_h265_depay_set_property (GObject * object, guint prop_id,
|
||||
case PROP_WAIT_FOR_KEYFRAME:
|
||||
self->wait_for_keyframe = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_REQUEST_KEYFRAME:
|
||||
self->request_keyframe = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -153,6 +158,9 @@ gst_rtp_h265_depay_get_property (GObject * object, guint prop_id,
|
||||
case PROP_WAIT_FOR_KEYFRAME:
|
||||
g_value_set_boolean (value, self->wait_for_keyframe);
|
||||
break;
|
||||
case PROP_REQUEST_KEYFRAME:
|
||||
g_value_set_boolean (value, self->request_keyframe);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -191,6 +199,19 @@ gst_rtp_h265_depay_class_init (GstRtpH265DepayClass * klass)
|
||||
DEFAULT_WAIT_FOR_KEYFRAME,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstRtpH265Depay:request-keyframe:
|
||||
*
|
||||
* Request new keyframe when packet loss is detected.
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
g_object_class_install_property (gobject_class, PROP_REQUEST_KEYFRAME,
|
||||
g_param_spec_boolean ("request-keyframe", "Request Keyframe",
|
||||
"Request new keyframe when packet loss is detected",
|
||||
DEFAULT_REQUEST_KEYFRAME,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gst_element_class_add_static_pad_template (gstelement_class,
|
||||
&gst_rtp_h265_depay_src_template);
|
||||
gst_element_class_add_static_pad_template (gstelement_class,
|
||||
@ -227,6 +248,7 @@ gst_rtp_h265_depay_init (GstRtpH265Depay * rtph265depay)
|
||||
rtph265depay->pps = g_ptr_array_new_with_free_func (
|
||||
(GDestroyNotify) gst_buffer_unref);
|
||||
rtph265depay->wait_for_keyframe = DEFAULT_WAIT_FOR_KEYFRAME;
|
||||
rtph265depay->request_keyframe = DEFAULT_REQUEST_KEYFRAME;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -235,6 +257,7 @@ gst_rtp_h265_depay_reset (GstRtpH265Depay * rtph265depay, gboolean hard)
|
||||
gst_adapter_clear (rtph265depay->adapter);
|
||||
rtph265depay->wait_start = TRUE;
|
||||
rtph265depay->waiting_for_keyframe = rtph265depay->wait_for_keyframe;
|
||||
rtph265depay->requesting_keyframe = FALSE;
|
||||
gst_adapter_clear (rtph265depay->picture_adapter);
|
||||
rtph265depay->picture_start = FALSE;
|
||||
rtph265depay->last_keyframe = FALSE;
|
||||
@ -1256,8 +1279,10 @@ gst_rtp_h265_depay_handle_nal (GstRtpH265Depay * rtph265depay, GstBuffer * nal,
|
||||
/* add to adapter */
|
||||
gst_buffer_unmap (nal, &map);
|
||||
|
||||
if (!rtph265depay->picture_start && start && out_keyframe)
|
||||
if (!rtph265depay->picture_start && start && out_keyframe) {
|
||||
rtph265depay->waiting_for_keyframe = FALSE;
|
||||
rtph265depay->requesting_keyframe = FALSE;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (depayload, "adding NAL to picture adapter");
|
||||
gst_adapter_push (rtph265depay->picture_adapter, nal);
|
||||
@ -1276,7 +1301,17 @@ gst_rtp_h265_depay_handle_nal (GstRtpH265Depay * rtph265depay, GstBuffer * nal,
|
||||
}
|
||||
|
||||
if (outbuf) {
|
||||
if (!rtph265depay->waiting_for_keyframe) {
|
||||
/* Request a new keyframe if we are waiting for one */
|
||||
if (rtph265depay->waiting_for_keyframe &&
|
||||
!rtph265depay->requesting_keyframe && rtph265depay->request_keyframe) {
|
||||
rtph265depay->requesting_keyframe = TRUE;
|
||||
GST_INFO_OBJECT (depayload, "Requesting keyframe while waiting for one");
|
||||
gst_pad_push_event (GST_RTP_BASE_DEPAYLOAD_SINKPAD (depayload),
|
||||
gst_video_event_new_upstream_force_key_unit (GST_CLOCK_TIME_NONE,
|
||||
TRUE, 0));
|
||||
}
|
||||
|
||||
if (!rtph265depay->waiting_for_keyframe || !rtph265depay->wait_for_keyframe) {
|
||||
GST_INFO_OBJECT (depayload, "Pushing frame %" GST_PTR_FORMAT, outbuf);
|
||||
gst_rtp_h265_depay_push (rtph265depay, outbuf, out_keyframe,
|
||||
out_timestamp, marker);
|
||||
@ -1333,23 +1368,26 @@ gst_rtp_h265_depay_process (GstRTPBaseDepayload * depayload, GstRTPBuffer * rtp)
|
||||
{
|
||||
GstRtpH265Depay *rtph265depay;
|
||||
GstBuffer *outbuf = NULL;
|
||||
gboolean is_discont;
|
||||
guint8 nal_unit_type;
|
||||
|
||||
rtph265depay = GST_RTP_H265_DEPAY (depayload);
|
||||
|
||||
if (!rtph265depay->merge)
|
||||
if (!rtph265depay->merge) {
|
||||
rtph265depay->waiting_for_keyframe = FALSE;
|
||||
rtph265depay->requesting_keyframe = FALSE;
|
||||
}
|
||||
|
||||
/* flush remaining data on discont */
|
||||
if (GST_BUFFER_IS_DISCONT (rtp->buffer)) {
|
||||
is_discont = GST_BUFFER_IS_DISCONT (rtp->buffer);
|
||||
if (is_discont) {
|
||||
gst_adapter_clear (rtph265depay->adapter);
|
||||
rtph265depay->wait_start = TRUE;
|
||||
rtph265depay->current_fu_type = 0;
|
||||
rtph265depay->last_fu_seqnum = 0;
|
||||
|
||||
if (rtph265depay->merge && rtph265depay->wait_for_keyframe) {
|
||||
if (rtph265depay->merge)
|
||||
rtph265depay->waiting_for_keyframe = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@ -1589,6 +1627,16 @@ gst_rtp_h265_depay_process (GstRTPBaseDepayload * depayload, GstRTPBuffer * rtp)
|
||||
/* and assemble in the adapter */
|
||||
gst_adapter_push (rtph265depay->adapter, outbuf);
|
||||
} else {
|
||||
/* If packet is discont and is not the first one of a FU, then we
|
||||
* can tell it is not part of a keyframe, so request a new one */
|
||||
if (is_discont && rtph265depay->request_keyframe) {
|
||||
GST_INFO_OBJECT (depayload,
|
||||
"discont FU received without start bit. Requesting keyframe.");
|
||||
gst_pad_push_event (GST_RTP_BASE_DEPAYLOAD_SINKPAD (depayload),
|
||||
gst_video_event_new_upstream_force_key_unit
|
||||
(GST_CLOCK_TIME_NONE, TRUE, 0));
|
||||
}
|
||||
|
||||
if (rtph265depay->current_fu_type == 0) {
|
||||
/* previous FU packet missing start bit? */
|
||||
GST_WARNING_OBJECT (rtph265depay, "missing FU start bit on an "
|
||||
|
@ -90,6 +90,7 @@ struct _GstRtpH265Depay
|
||||
gboolean wait_for_keyframe;
|
||||
gboolean request_keyframe;
|
||||
gboolean waiting_for_keyframe;
|
||||
gboolean requesting_keyframe;
|
||||
};
|
||||
|
||||
struct _GstRtpH265DepayClass
|
||||
|
Loading…
x
Reference in New Issue
Block a user