mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 18:21:04 +00:00
rtptheoradepay: Request new keyframe on lost packets
Theora can only use the last frame (or the keyframe) as a reference, so in practice. If we receive a buffer that references an unknown codebook, request new headers. It probably means that headers were lost.
This commit is contained in:
parent
cd923223dd
commit
8a7a327db7
2 changed files with 51 additions and 3 deletions
|
@ -67,6 +67,8 @@ static gboolean gst_rtp_theora_depay_setcaps (GstBaseRTPDepayload * depayload,
|
||||||
GstCaps * caps);
|
GstCaps * caps);
|
||||||
static GstBuffer *gst_rtp_theora_depay_process (GstBaseRTPDepayload * depayload,
|
static GstBuffer *gst_rtp_theora_depay_process (GstBaseRTPDepayload * depayload,
|
||||||
GstBuffer * buf);
|
GstBuffer * buf);
|
||||||
|
static gboolean gst_rtp_theora_depay_packet_lost (GstBaseRTPDepayload *
|
||||||
|
depayload, GstEvent * event);
|
||||||
|
|
||||||
static void gst_rtp_theora_depay_finalize (GObject * object);
|
static void gst_rtp_theora_depay_finalize (GObject * object);
|
||||||
|
|
||||||
|
@ -100,6 +102,7 @@ gst_rtp_theora_depay_class_init (GstRtpTheoraDepayClass * klass)
|
||||||
|
|
||||||
gstbasertpdepayload_class->process = gst_rtp_theora_depay_process;
|
gstbasertpdepayload_class->process = gst_rtp_theora_depay_process;
|
||||||
gstbasertpdepayload_class->set_caps = gst_rtp_theora_depay_setcaps;
|
gstbasertpdepayload_class->set_caps = gst_rtp_theora_depay_setcaps;
|
||||||
|
gstbasertpdepayload_class->packet_lost = gst_rtp_theora_depay_packet_lost;
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (rtptheoradepay_debug, "rtptheoradepay", 0,
|
GST_DEBUG_CATEGORY_INIT (rtptheoradepay_debug, "rtptheoradepay", 0,
|
||||||
"Theora RTP Depayloader");
|
"Theora RTP Depayloader");
|
||||||
|
@ -308,6 +311,8 @@ gst_rtp_theora_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
|
||||||
|
|
||||||
rtptheoradepay = GST_RTP_THEORA_DEPAY (depayload);
|
rtptheoradepay = GST_RTP_THEORA_DEPAY (depayload);
|
||||||
|
|
||||||
|
rtptheoradepay->needs_keyframe = FALSE;
|
||||||
|
|
||||||
structure = gst_caps_get_structure (caps, 0);
|
structure = gst_caps_get_structure (caps, 0);
|
||||||
|
|
||||||
/* read and parse configuration string */
|
/* read and parse configuration string */
|
||||||
|
@ -554,6 +559,9 @@ gst_rtp_theora_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
memcpy (GST_BUFFER_DATA (outbuf), payload, length);
|
memcpy (GST_BUFFER_DATA (outbuf), payload, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((payload[0] & 0xC0) == 0x0)
|
||||||
|
rtptheoradepay->needs_keyframe = FALSE;
|
||||||
|
|
||||||
payload += length;
|
payload += length;
|
||||||
payload_len -= length;
|
payload_len -= length;
|
||||||
|
|
||||||
|
@ -573,6 +581,9 @@ gst_rtp_theora_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
|
|
||||||
g_free (to_free);
|
g_free (to_free);
|
||||||
|
|
||||||
|
if (rtptheoradepay->needs_keyframe)
|
||||||
|
goto request_keyframe;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
no_output:
|
no_output:
|
||||||
|
@ -584,13 +595,13 @@ switch_failed:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_WARNING (rtptheoradepay, STREAM, DECODE,
|
GST_ELEMENT_WARNING (rtptheoradepay, STREAM, DECODE,
|
||||||
(NULL), ("Could not switch codebooks"));
|
(NULL), ("Could not switch codebooks"));
|
||||||
return NULL;
|
goto request_config;
|
||||||
}
|
}
|
||||||
packet_short:
|
packet_short:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_WARNING (rtptheoradepay, STREAM, DECODE,
|
GST_ELEMENT_WARNING (rtptheoradepay, STREAM, DECODE,
|
||||||
(NULL), ("Packet was too short (%d < 4)", payload_len));
|
(NULL), ("Packet was too short (%d < 4)", payload_len));
|
||||||
return NULL;
|
goto request_keyframe;
|
||||||
}
|
}
|
||||||
ignore_reserved:
|
ignore_reserved:
|
||||||
{
|
{
|
||||||
|
@ -601,13 +612,29 @@ length_short:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_WARNING (rtptheoradepay, STREAM, DECODE,
|
GST_ELEMENT_WARNING (rtptheoradepay, STREAM, DECODE,
|
||||||
(NULL), ("Packet contains invalid data"));
|
(NULL), ("Packet contains invalid data"));
|
||||||
return NULL;
|
goto request_keyframe;
|
||||||
}
|
}
|
||||||
invalid_configuration:
|
invalid_configuration:
|
||||||
{
|
{
|
||||||
/* fatal, as we otherwise risk carrying on without output */
|
/* fatal, as we otherwise risk carrying on without output */
|
||||||
GST_ELEMENT_ERROR (rtptheoradepay, STREAM, DECODE,
|
GST_ELEMENT_ERROR (rtptheoradepay, STREAM, DECODE,
|
||||||
(NULL), ("Packet contains invalid configuration"));
|
(NULL), ("Packet contains invalid configuration"));
|
||||||
|
goto request_config;
|
||||||
|
}
|
||||||
|
request_config:
|
||||||
|
{
|
||||||
|
gst_pad_push_event (GST_BASE_RTP_DEPAYLOAD_SINKPAD (depayload),
|
||||||
|
gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM,
|
||||||
|
gst_structure_new ("GstForceKeyUnit",
|
||||||
|
"all-headers", G_TYPE_BOOLEAN, TRUE, NULL)));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
request_keyframe:
|
||||||
|
{
|
||||||
|
rtptheoradepay->needs_keyframe = TRUE;
|
||||||
|
gst_pad_push_event (GST_BASE_RTP_DEPAYLOAD_SINKPAD (depayload),
|
||||||
|
gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM,
|
||||||
|
gst_structure_new ("GstForceKeyUnit", NULL)));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -618,3 +645,22 @@ gst_rtp_theora_depay_plugin_init (GstPlugin * plugin)
|
||||||
return gst_element_register (plugin, "rtptheoradepay",
|
return gst_element_register (plugin, "rtptheoradepay",
|
||||||
GST_RANK_SECONDARY, GST_TYPE_RTP_THEORA_DEPAY);
|
GST_RANK_SECONDARY, GST_TYPE_RTP_THEORA_DEPAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_rtp_theora_depay_packet_lost (GstBaseRTPDepayload * depayload,
|
||||||
|
GstEvent * event)
|
||||||
|
{
|
||||||
|
GstRtpTheoraDepay *rtptheoradepay = GST_RTP_THEORA_DEPAY (depayload);
|
||||||
|
guint seqnum = 0;
|
||||||
|
|
||||||
|
gst_structure_get_uint (event->structure, "seqnum", &seqnum);
|
||||||
|
GST_LOG_OBJECT (depayload, "Requested keyframe because frame with seqnum %u"
|
||||||
|
" is missing", seqnum);
|
||||||
|
rtptheoradepay->needs_keyframe = TRUE;
|
||||||
|
|
||||||
|
gst_pad_push_event (GST_BASE_RTP_DEPAYLOAD_SINKPAD (depayload),
|
||||||
|
gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM,
|
||||||
|
gst_structure_new ("GstForceKeyUnit", NULL)));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
|
@ -54,6 +54,8 @@ struct _GstRtpTheoraDepay
|
||||||
|
|
||||||
GstAdapter *adapter;
|
GstAdapter *adapter;
|
||||||
gboolean assembling;
|
gboolean assembling;
|
||||||
|
|
||||||
|
gboolean needs_keyframe;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstRtpTheoraDepayClass
|
struct _GstRtpTheoraDepayClass
|
||||||
|
|
Loading…
Reference in a new issue