mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +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);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,8 @@ struct _GstRtpTheoraDepay
|
|||
|
||||
GstAdapter *adapter;
|
||||
gboolean assembling;
|
||||
|
||||
gboolean needs_keyframe;
|
||||
};
|
||||
|
||||
struct _GstRtpTheoraDepayClass
|
||||
|
|
Loading…
Reference in a new issue