katedec: handle streamheaders in caps

Properly handle the caps event by configuring the kate decoding lib using the
available streamheaders. This makes it possible to decode kate subtitles when
the stream is seeked before katedec gets the initial buffers that are usually
the streamheaders.

https://bugzilla.gnome.org/show_bug.cgi?id=733226
This commit is contained in:
Thiago Santos 2014-07-15 16:41:51 -03:00
parent 83b672f328
commit b0e63bbb9b

View file

@ -237,36 +237,11 @@ gst_kate_dec_get_property (GObject * object, guint prop_id,
} }
} }
/* GstElement vmethod implementations */
/* chain function
* this function does the actual processing
*/
static GstFlowReturn static GstFlowReturn
gst_kate_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) gst_kate_dec_handle_kate_event (GstKateDec * kd, const kate_event * ev)
{ {
GstKateFormat format = GST_KATE_FORMAT_UNDEFINED;
GstKateDec *kd = GST_KATE_DEC (parent);
const kate_event *ev = NULL;
GstFlowReturn rflow = GST_FLOW_OK; GstFlowReturn rflow = GST_FLOW_OK;
GstKateFormat format = GST_KATE_FORMAT_UNDEFINED;
if (!gst_kate_util_decoder_base_update_segment (&kd->decoder,
GST_ELEMENT_CAST (kd), buf)) {
GST_WARNING_OBJECT (kd, "Out of segment!");
goto not_in_seg;
}
rflow =
gst_kate_util_decoder_base_chain_kate_packet (&kd->decoder,
GST_ELEMENT_CAST (kd), pad, buf, kd->srcpad, kd->srcpad, &kd->src_caps,
&ev);
if (G_UNLIKELY (rflow != GST_FLOW_OK)) {
gst_buffer_unref (buf);
return rflow;
}
if (ev) {
gchar *escaped; gchar *escaped;
GstBuffer *buffer; GstBuffer *buffer;
size_t len; size_t len;
@ -367,6 +342,39 @@ gst_kate_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
rflow = GST_FLOW_ERROR; rflow = GST_FLOW_ERROR;
} }
} }
return rflow;
}
/* GstElement vmethod implementations */
/* chain function
* this function does the actual processing
*/
static GstFlowReturn
gst_kate_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
GstKateDec *kd = GST_KATE_DEC (parent);
const kate_event *ev = NULL;
GstFlowReturn rflow = GST_FLOW_OK;
if (!gst_kate_util_decoder_base_update_segment (&kd->decoder,
GST_ELEMENT_CAST (kd), buf)) {
GST_WARNING_OBJECT (kd, "Out of segment!");
goto not_in_seg;
}
rflow =
gst_kate_util_decoder_base_chain_kate_packet (&kd->decoder,
GST_ELEMENT_CAST (kd), pad, buf, kd->srcpad, kd->srcpad, &kd->src_caps,
&ev);
if (G_UNLIKELY (rflow != GST_FLOW_OK)) {
gst_buffer_unref (buf);
return rflow;
}
if (ev) {
rflow = gst_kate_dec_handle_kate_event (kd, ev);
} }
not_in_seg: not_in_seg:
@ -400,13 +408,74 @@ gst_kate_dec_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
return res; return res;
} }
static gboolean
gst_kate_dec_set_caps (GstKateDec * kd, GstCaps * caps)
{
GstStructure *structure = gst_caps_get_structure (caps, 0);
GstFlowReturn rflow = GST_FLOW_OK;
if (gst_structure_has_field (structure, "streamheader")) {
const GValue *value;
GstBuffer *buf;
const kate_event *ev;
value = gst_structure_get_value (structure, "streamheader");
if (GST_VALUE_HOLDS_BUFFER (value)) {
buf = gst_value_get_buffer (value);
gst_kate_util_decoder_base_chain_kate_packet (&kd->decoder,
GST_ELEMENT_CAST (kd), kd->sinkpad, buf, kd->srcpad, kd->srcpad,
&kd->src_caps, &ev);
if (ev) {
rflow = gst_kate_dec_handle_kate_event (kd, ev);
}
} else if (GST_VALUE_HOLDS_ARRAY (value)) {
gint i, size = gst_value_array_get_size (value);
for (i = 0; i < size; i++) {
const GValue *v = gst_value_array_get_value (value, i);
buf = gst_value_get_buffer (v);
gst_kate_util_decoder_base_chain_kate_packet (&kd->decoder,
GST_ELEMENT_CAST (kd), kd->sinkpad, buf, kd->srcpad, kd->srcpad,
&kd->src_caps, &ev);
if (ev) {
rflow = gst_kate_dec_handle_kate_event (kd, ev);
if (rflow != GST_FLOW_OK && rflow != GST_FLOW_NOT_LINKED)
break;
}
}
} else {
GST_WARNING_OBJECT (kd, "Unhandled streamheader type: %s",
G_VALUE_TYPE_NAME (value));
}
}
return rflow == GST_FLOW_OK || rflow == GST_FLOW_NOT_LINKED;
}
static gboolean static gboolean
gst_kate_dec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) gst_kate_dec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
{ {
GstKateDec *kd = GST_KATE_DEC (parent); GstKateDec *kd = GST_KATE_DEC (parent);
gboolean res = TRUE; gboolean res = TRUE;
GST_LOG_OBJECT (pad, "Event on sink pad: %s", GST_EVENT_TYPE_NAME (event)); GST_LOG_OBJECT (pad, "Event on sink pad: %" GST_PTR_FORMAT, event);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_CAPS:{
GstCaps *caps;
gst_event_parse_caps (event, &caps);
gst_kate_dec_set_caps (kd, caps);
break;
}
default:
break;
}
/* Delay events till we've set caps */ /* Delay events till we've set caps */
if (gst_kate_util_decoder_base_queue_event (&kd->decoder, event, if (gst_kate_util_decoder_base_queue_event (&kd->decoder, event,