summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier CrĂȘte <olivier.crete@collabora.co.uk>2010-10-06 21:17:28 -0400
committerWim Taymans <wim.taymans@collabora.co.uk>2011-02-01 18:28:51 +0100
commit8a7a327db7dd0e677844599f4a0db76a7d06b512 (patch)
treed8dc68f26ad896d0c9312aafe9b868c832efa679
parentcd923223dd24576679ff91deda71cc8f172504c3 (diff)
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.
-rw-r--r--gst/rtp/gstrtptheoradepay.c52
-rw-r--r--gst/rtp/gstrtptheoradepay.h2
2 files changed, 51 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;
+}
diff --git a/gst/rtp/gstrtptheoradepay.h b/gst/rtp/gstrtptheoradepay.h
index 0d1a911f9..dff261c43 100644
--- a/gst/rtp/gstrtptheoradepay.h
+++ b/gst/rtp/gstrtptheoradepay.h
@@ -54,6 +54,8 @@ struct _GstRtpTheoraDepay
GstAdapter *adapter;
gboolean assembling;
+
+ gboolean needs_keyframe;
};
struct _GstRtpTheoraDepayClass