summaryrefslogtreecommitdiff
path: root/gst/rtp/gstrtptheoradepay.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/rtp/gstrtptheoradepay.c')
-rw-r--r--gst/rtp/gstrtptheoradepay.c52
1 files changed, 49 insertions, 3 deletions
diff --git a/gst/rtp/gstrtptheoradepay.c b/gst/rtp/gstrtptheoradepay.c
index dfe6de3d4..a21cc6c6d 100644
--- a/gst/rtp/gstrtptheoradepay.c
+++ b/gst/rtp/gstrtptheoradepay.c
@@ -67,6 +67,8 @@ static gboolean gst_rtp_theora_depay_setcaps (GstBaseRTPDepayload * depayload,
GstCaps * caps);
static GstBuffer *gst_rtp_theora_depay_process (GstBaseRTPDepayload * depayload,
GstBuffer * buf);
+static gboolean gst_rtp_theora_depay_packet_lost (GstBaseRTPDepayload *
+ depayload, GstEvent * event);
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->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,
"Theora RTP Depayloader");
@@ -308,6 +311,8 @@ gst_rtp_theora_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
rtptheoradepay = GST_RTP_THEORA_DEPAY (depayload);
+ rtptheoradepay->needs_keyframe = FALSE;
+
structure = gst_caps_get_structure (caps, 0);
/* 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);
}
+ if ((payload[0] & 0xC0) == 0x0)
+ rtptheoradepay->needs_keyframe = FALSE;
+
payload += length;
payload_len -= length;
@@ -573,6 +581,9 @@ gst_rtp_theora_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
g_free (to_free);
+ if (rtptheoradepay->needs_keyframe)
+ goto request_keyframe;
+
return NULL;
no_output:
@@ -584,13 +595,13 @@ switch_failed:
{
GST_ELEMENT_WARNING (rtptheoradepay, STREAM, DECODE,
(NULL), ("Could not switch codebooks"));
- return NULL;
+ goto request_config;
}
packet_short:
{
GST_ELEMENT_WARNING (rtptheoradepay, STREAM, DECODE,
(NULL), ("Packet was too short (%d < 4)", payload_len));
- return NULL;
+ goto request_keyframe;
}
ignore_reserved:
{
@@ -601,13 +612,29 @@ length_short:
{
GST_ELEMENT_WARNING (rtptheoradepay, STREAM, DECODE,
(NULL), ("Packet contains invalid data"));
- return NULL;
+ goto request_keyframe;
}
invalid_configuration:
{
/* fatal, as we otherwise risk carrying on without output */
GST_ELEMENT_ERROR (rtptheoradepay, STREAM, DECODE,
(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;
}
}
@@ -618,3 +645,22 @@ gst_rtp_theora_depay_plugin_init (GstPlugin * plugin)
return gst_element_register (plugin, "rtptheoradepay",
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;
+}