summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Penquerc'h <ogg.k.ogg.k@googlemail.com>2010-01-25 18:58:38 +0000
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2010-12-25 16:59:22 +0100
commit8574e8f991f68506af3a0c369c933020688bd4c3 (patch)
tree955321ae9406e1fe7ac6c8155bf561f7a6e65d35
parent4422cca1d3f98fcc68895e9a051f38dc22d4f7d7 (diff)
kate: add segment tracking, and various other improvements
https://bugzilla.gnome.org/show_bug.cgi?id=600929
-rw-r--r--ext/kate/Makefile.am2
-rw-r--r--ext/kate/gstkate.c3
-rw-r--r--ext/kate/gstkatedec.c105
-rw-r--r--ext/kate/gstkatedec.h4
-rw-r--r--ext/kate/gstkateparse.c5
-rw-r--r--ext/kate/gstkatespu.c8
-rw-r--r--ext/kate/gstkatetiger.c321
-rw-r--r--ext/kate/gstkatetiger.h8
-rw-r--r--ext/kate/gstkateutil.c206
-rw-r--r--ext/kate/gstkateutil.h30
10 files changed, 600 insertions, 92 deletions
diff --git a/ext/kate/Makefile.am b/ext/kate/Makefile.am
index 6a2152d13..fd7d6ced4 100644
--- a/ext/kate/Makefile.am
+++ b/ext/kate/Makefile.am
@@ -10,7 +10,7 @@ endif
# flags used to compile this plugin
libgstkate_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(TIGER_CFLAGS) $(KATE_CFLAGS)
-libgstkate_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_MAJORMINOR) $(GST_LIBS) $(TIGER_LIBS) $(KATE_LIBS)
+libgstkate_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) -lgsttag-$(GST_MAJORMINOR) $(GST_LIBS) $(TIGER_LIBS) $(KATE_LIBS)
libgstkate_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstkate_la_LIBTOOLFLAGS = --tag=disable-static
diff --git a/ext/kate/gstkate.c b/ext/kate/gstkate.c
index 08adfea8d..91d0579a6 100644
--- a/ext/kate/gstkate.c
+++ b/ext/kate/gstkate.c
@@ -64,6 +64,7 @@ GST_DEBUG_CATEGORY (gst_katedec_debug);
GST_DEBUG_CATEGORY (gst_kateenc_debug);
GST_DEBUG_CATEGORY (gst_kateparse_debug);
GST_DEBUG_CATEGORY (gst_katetag_debug);
+GST_DEBUG_CATEGORY (gst_kateutil_debug);
#ifdef HAVE_TIGER
GST_DEBUG_CATEGORY (gst_katetiger_debug);
#endif
@@ -75,6 +76,8 @@ plugin_init (GstPlugin * plugin)
GST_DEBUG_CATEGORY_INIT (gst_kateenc_debug, "kateenc", 0, "Kate encoder");
GST_DEBUG_CATEGORY_INIT (gst_kateparse_debug, "kateparse", 0, "Kate parser");
GST_DEBUG_CATEGORY_INIT (gst_katetag_debug, "katetag", 0, "Kate tagger");
+ GST_DEBUG_CATEGORY_INIT (gst_kateutil_debug, "kateutil", 0,
+ "Kate utility functions");
#ifdef HAVE_TIGER
GST_DEBUG_CATEGORY_INIT (gst_katetiger_debug, "tiger", 0,
"Kate Tiger renderer");
diff --git a/ext/kate/gstkatedec.c b/ext/kate/gstkatedec.c
index 322363d81..4dbe6d818 100644
--- a/ext/kate/gstkatedec.c
+++ b/ext/kate/gstkatedec.c
@@ -128,6 +128,9 @@ static GstFlowReturn gst_kate_dec_chain (GstPad * pad, GstBuffer * buf);
static GstStateChangeReturn gst_kate_dec_change_state (GstElement * element,
GstStateChange transition);
static gboolean gst_kate_dec_sink_query (GstPad * pad, GstQuery * query);
+static gboolean gst_kate_dec_sink_event (GstPad * pad, GstEvent * event);
+static gboolean gst_kate_dec_sink_handle_event (GstPad * pad, GstEvent * event);
+static GstCaps *gst_kate_dec_src_get_caps (GstPad * pad);
static void
gst_kate_dec_base_init (gpointer gclass)
@@ -184,16 +187,21 @@ gst_kate_dec_init (GstKateDec * dec, GstKateDecClass * gclass)
GST_DEBUG_FUNCPTR (gst_kate_dec_chain));
gst_pad_set_query_function (dec->sinkpad,
GST_DEBUG_FUNCPTR (gst_kate_dec_sink_query));
+ gst_pad_set_event_function (dec->sinkpad,
+ GST_DEBUG_FUNCPTR (gst_kate_dec_sink_event));
gst_pad_use_fixed_caps (dec->sinkpad);
gst_pad_set_caps (dec->sinkpad,
gst_static_pad_template_get_caps (&sink_factory));
gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
dec->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
+ gst_pad_set_getcaps_function (dec->srcpad,
+ GST_DEBUG_FUNCPTR (gst_kate_dec_src_get_caps));
gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
- gst_kate_util_decode_base_init (&dec->decoder);
+ gst_kate_util_decode_base_init (&dec->decoder, TRUE);
+ dec->src_caps = NULL;
dec->remove_markup = FALSE;
}
@@ -240,9 +248,16 @@ gst_kate_dec_chain (GstPad * pad, GstBuffer * buf)
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, &ev);
+ GST_ELEMENT_CAST (kd), pad, buf, kd->srcpad, kd->srcpad, &kd->src_caps,
+ &ev);
if (G_UNLIKELY (rflow != GST_FLOW_OK)) {
gst_object_unref (kd);
gst_buffer_unref (buf);
@@ -336,6 +351,7 @@ gst_kate_dec_chain (GstPad * pad, GstBuffer * buf)
}
}
+not_in_seg:
gst_object_unref (kd);
gst_buffer_unref (buf);
return rflow;
@@ -345,6 +361,7 @@ static GstStateChangeReturn
gst_kate_dec_change_state (GstElement * element, GstStateChange transition)
{
GstKateDec *kd = GST_KATE_DEC (element);
+
return gst_kate_decoder_base_change_state (&kd->decoder, element,
parent_class, transition);
}
@@ -359,3 +376,87 @@ gst_kate_dec_sink_query (GstPad * pad, GstQuery * query)
gst_object_unref (kd);
return res;
}
+
+static gboolean
+gst_kate_dec_sink_event (GstPad * pad, GstEvent * event)
+{
+ GstKateDec *kd = (GstKateDec *) (gst_object_get_parent (GST_OBJECT (pad)));
+ gboolean res = TRUE;
+
+ g_return_val_if_fail (kd != NULL, FALSE);
+
+ GST_LOG_OBJECT (kd, "Event on sink pad: %s", GST_EVENT_TYPE_NAME (event));
+
+ // Delay events till we've set caps
+ if (gst_kate_util_decoder_base_queue_event (&kd->decoder, event,
+ &gst_kate_dec_sink_handle_event, pad)) {
+ gst_object_unref (kd);
+ return TRUE;
+ }
+
+ res = gst_kate_dec_sink_handle_event (pad, event);
+
+ gst_object_unref (kd);
+
+ return res;
+}
+
+static gboolean
+gst_kate_dec_sink_handle_event (GstPad * pad, GstEvent * event)
+{
+ GstKateDec *kd = (GstKateDec *) (gst_object_get_parent (GST_OBJECT (pad)));
+ gboolean res = TRUE;
+
+ g_return_val_if_fail (kd != NULL, FALSE);
+
+ GST_LOG_OBJECT (kd, "Handling event on sink pad: %s",
+ GST_EVENT_TYPE_NAME (event));
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_NEWSEGMENT:
+ gst_kate_util_decoder_base_new_segment_event (&kd->decoder, event);
+ res = gst_pad_event_default (pad, event);
+ break;
+
+ case GST_EVENT_FLUSH_START:
+ gst_kate_util_decoder_base_set_flushing (&kd->decoder, TRUE);
+ res = gst_pad_event_default (pad, event);
+ break;
+
+ case GST_EVENT_FLUSH_STOP:
+ gst_kate_util_decoder_base_set_flushing (&kd->decoder, FALSE);
+ res = gst_pad_event_default (pad, event);
+ break;
+
+ default:
+ res = gst_pad_event_default (pad, event);
+ break;
+ }
+
+ gst_object_unref (kd);
+
+ return res;
+}
+
+static GstCaps *
+gst_kate_dec_src_get_caps (GstPad * pad)
+{
+ GstKateDec *kd = (GstKateDec *) (gst_object_get_parent (GST_OBJECT (pad)));
+ GstCaps *caps;
+
+ g_return_val_if_fail (kd != NULL, FALSE);
+
+ if (kd->src_caps) {
+ GST_DEBUG_OBJECT (kd, "We have src caps (%s)",
+ gst_caps_to_string (kd->src_caps));
+ caps = kd->src_caps;
+ } else {
+ GST_DEBUG_OBJECT (kd, "We have no src caps, using template caps");
+ caps = gst_static_pad_template_get_caps (&src_factory);
+ }
+
+ caps = gst_caps_copy (caps);
+
+ gst_object_unref (kd);
+ return caps;
+}
diff --git a/ext/kate/gstkatedec.h b/ext/kate/gstkatedec.h
index a7011ecbc..b4d99059a 100644
--- a/ext/kate/gstkatedec.h
+++ b/ext/kate/gstkatedec.h
@@ -67,12 +67,12 @@ typedef struct _GstKateDecClass GstKateDecClass;
struct _GstKateDec
{
- GstElement element;
+ GstKateDecoderBase decoder;
GstPad *sinkpad;
GstPad *srcpad;
- GstKateDecoderBase decoder;
+ GstCaps *src_caps;
gboolean remove_markup;
};
diff --git a/ext/kate/gstkateparse.c b/ext/kate/gstkateparse.c
index c41066645..6a72edec9 100644
--- a/ext/kate/gstkateparse.c
+++ b/ext/kate/gstkateparse.c
@@ -255,11 +255,6 @@ gst_kate_parse_push_buffer (GstKateParse * parse, GstBuffer * buf,
GST_BUFFER_OFFSET_END (buf) = granulepos;
GST_BUFFER_TIMESTAMP (buf) = GST_BUFFER_OFFSET (buf);
- /* Hack to flush each packet on its own page - taken off the CMML encoder element */
- /* TODO: this is shite and needs to go once I find a way to tell Ogg to flush
- as it messes up Matroska's track duration */
- GST_BUFFER_DURATION (buf) = G_MAXINT64;
-
gst_buffer_set_caps (buf, GST_PAD_CAPS (parse->srcpad));
return gst_pad_push (parse->srcpad, buf);
diff --git a/ext/kate/gstkatespu.c b/ext/kate/gstkatespu.c
index 778288ecf..13f561941 100644
--- a/ext/kate/gstkatespu.c
+++ b/ext/kate/gstkatespu.c
@@ -804,14 +804,6 @@ gst_kate_spu_encode_spu (GstKateDec * kd, const kate_event * ev)
bytes[nbytes++] =
((kp->colors[palette[1]].a / 17) << 4) | (kp->colors[palette[0]].a / 17);
-#if 0
- // move to top left - avoids a crash in dvdspu when overlaying on a small video :/
- right -= left;
- bottom -= top;
- left = 0;
- top = 0;
-#endif
-
CHKBUFSPC (7 * 2);
bytes[nbytes++] = SPU_CMD_SET_DAREA;
bytes[nbytes++] = left >> 4;
diff --git a/ext/kate/gstkatetiger.c b/ext/kate/gstkatetiger.c
index 93d98e73a..286929796 100644
--- a/ext/kate/gstkatetiger.c
+++ b/ext/kate/gstkatetiger.c
@@ -88,6 +88,19 @@
GST_DEBUG_CATEGORY_EXTERN (gst_katetiger_debug);
#define GST_CAT_DEFAULT gst_katetiger_debug
+#define GST_KATE_TIGER_MUTEX_LOCK(element) \
+ do { \
+ /*GST_LOG_OBJECT ((element), "locking from %s:%d\n",__FILE__,__LINE__);*/ \
+ g_mutex_lock ((element)->mutex); \
+ /*GST_LOG_OBJECT ((element), "ready from %s:%d\n",__FILE__,__LINE__);*/ \
+ } while(0)
+
+#define GST_KATE_TIGER_MUTEX_UNLOCK(element) \
+ do { \
+ /*GST_LOG_OBJECT ((element), "unlocking from %s:%d\n",__FILE__,__LINE__);*/ \
+ g_mutex_unlock ((element)->mutex); \
+ } while(0)
+
/* Filter signals and args */
enum
{
@@ -119,16 +132,28 @@ static GstStaticPadTemplate kate_sink_factory =
);
static GstStaticPadTemplate video_sink_factory =
-GST_STATIC_PAD_TEMPLATE ("video_sink",
+ GST_STATIC_PAD_TEMPLATE ("video_sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-raw-rgb, bpp=(int)32, depth=(int)24")
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB ", endianness = (int) 1234" ";"
+ GST_VIDEO_CAPS_BGRx ", endianness = (int)4321")
+#else
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB ", endianness = (int) 4321" ";"
+ GST_VIDEO_CAPS_BGRx ", endianness = (int)1234")
+#endif
);
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-raw-rgb, bpp=(int)32, depth=(int)24")
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB ", endianness = (int) 1234" ";"
+ GST_VIDEO_CAPS_BGRx ", endianness = (int)4321")
+#else
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB ", endianness = (int) 4321" ";"
+ GST_VIDEO_CAPS_BGRx ", endianness = (int)1234")
+#endif
);
GST_BOILERPLATE (GstKateTiger, gst_kate_tiger, GstElement, GST_TYPE_ELEMENT);
@@ -163,6 +188,7 @@ static GstStateChangeReturn gst_kate_tiger_change_state (GstElement * element,
GstStateChange transition);
static gboolean gst_kate_tiger_kate_sink_query (GstPad * pad, GstQuery * query);
static gboolean gst_kate_tiger_kate_event (GstPad * pad, GstEvent * event);
+static gboolean gst_kate_tiger_video_event (GstPad * pad, GstEvent * event);
static gboolean gst_kate_tiger_video_set_caps (GstPad * pad, GstCaps * caps);
static gboolean gst_kate_tiger_source_event (GstPad * pad, GstEvent * event);
@@ -302,19 +328,19 @@ gst_kate_tiger_init (GstKateTiger * tiger, GstKateTigerClass * gclass)
gst_pad_new_from_static_template (&video_sink_factory, "video_sink");
gst_pad_set_chain_function (tiger->videosinkpad,
GST_DEBUG_FUNCPTR (gst_kate_tiger_video_chain));
- //gst_pad_set_query_function (tiger->videosinkpad, GST_DEBUG_FUNCPTR (gst_kate_tiger_video_sink_query));
gst_pad_use_fixed_caps (tiger->videosinkpad);
- gst_pad_set_caps (tiger->videosinkpad,
- gst_static_pad_template_get_caps (&video_sink_factory));
gst_pad_set_setcaps_function (tiger->videosinkpad,
GST_DEBUG_FUNCPTR (gst_kate_tiger_video_set_caps));
+ gst_pad_set_event_function (tiger->videosinkpad,
+ GST_DEBUG_FUNCPTR (gst_kate_tiger_video_event));
gst_element_add_pad (GST_ELEMENT (tiger), tiger->videosinkpad);
tiger->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
gst_pad_set_event_function (tiger->srcpad, gst_kate_tiger_source_event);
+ gst_pad_use_fixed_caps (tiger->srcpad);
gst_element_add_pad (GST_ELEMENT (tiger), tiger->srcpad);
- gst_kate_util_decode_base_init (&tiger->decoder);
+ gst_kate_util_decode_base_init (&tiger->decoder, FALSE);
tiger->tr = NULL;
@@ -400,7 +426,7 @@ gst_kate_tiger_set_property (GObject * object, guint prop_id,
GstKateTiger *tiger = GST_KATE_TIGER (object);
const char *str;
- g_mutex_lock (tiger->mutex);
+ GST_KATE_TIGER_MUTEX_LOCK (tiger);
switch (prop_id) {
case ARG_DEFAULT_FONT_DESC:
@@ -465,7 +491,7 @@ gst_kate_tiger_set_property (GObject * object, guint prop_id,
break;
}
- g_mutex_unlock (tiger->mutex);
+ GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
}
static void
@@ -474,7 +500,7 @@ gst_kate_tiger_get_property (GObject * object, guint prop_id,
{
GstKateTiger *tiger = GST_KATE_TIGER (object);
- g_mutex_lock (tiger->mutex);
+ GST_KATE_TIGER_MUTEX_LOCK (tiger);
switch (prop_id) {
case ARG_DEFAULT_FONT_DESC:
@@ -522,7 +548,7 @@ gst_kate_tiger_get_property (GObject * object, guint prop_id,
break;
}
- g_mutex_unlock (tiger->mutex);
+ GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
}
/* GstElement vmethod implementations */
@@ -538,30 +564,36 @@ gst_kate_tiger_kate_chain (GstPad * pad, GstBuffer * buf)
const kate_event *ev = NULL;
GstFlowReturn rflow = GST_FLOW_OK;
- g_mutex_lock (tiger->mutex);
-
- GST_LOG_OBJECT (tiger, "Got kate buffer");
-
- rflow =
- gst_kate_util_decoder_base_chain_kate_packet (&tiger->decoder,
- GST_ELEMENT_CAST (tiger), pad, buf, tiger->srcpad, &ev);
- if (G_LIKELY (rflow == GST_FLOW_OK)) {
- if (ev) {
- int ret = tiger_renderer_add_event (tiger->tr, ev->ki, ev);
- GST_INFO_OBJECT (tiger, "adding event for %p from %f to %f: %p, \"%s\"",
- ev->ki, ev->start_time, ev->end_time, ev->bitmap, ev->text);
- if (G_UNLIKELY (ret < 0)) {
- GST_WARNING_OBJECT (tiger,
- "failed to add Kate event to Tiger renderer: %d", ret);
+ GST_KATE_TIGER_MUTEX_LOCK (tiger);
+
+ GST_LOG_OBJECT (tiger, "Got kate buffer, caps %s",
+ gst_caps_to_string (GST_BUFFER_CAPS (buf)));
+
+ if (gst_kate_util_decoder_base_update_segment (&tiger->decoder,
+ GST_ELEMENT_CAST (tiger), buf)) {
+ GstPad *tagpad = gst_pad_get_peer (pad);
+ rflow =
+ gst_kate_util_decoder_base_chain_kate_packet (&tiger->decoder,
+ GST_ELEMENT_CAST (tiger), pad, buf, tiger->srcpad, tagpad, NULL, &ev);
+ if (G_LIKELY (rflow == GST_FLOW_OK)) {
+ if (ev) {
+ int ret = tiger_renderer_add_event (tiger->tr, ev->ki, ev);
+ GST_INFO_OBJECT (tiger, "adding event for %p from %f to %f: %p, \"%s\"",
+ ev->ki, ev->start_time, ev->end_time, ev->bitmap, ev->text);
+ if (G_UNLIKELY (ret < 0)) {
+ GST_WARNING_OBJECT (tiger,
+ "failed to add Kate event to Tiger renderer: %d", ret);
+ }
}
}
+ gst_object_unref (tagpad);
}
+ GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
+
gst_object_unref (tiger);
gst_buffer_unref (buf);
- g_mutex_unlock (tiger->mutex);
-
return rflow;
}
@@ -569,28 +601,36 @@ static gboolean
gst_kate_tiger_video_set_caps (GstPad * pad, GstCaps * caps)
{
GstKateTiger *tiger = GST_KATE_TIGER (gst_pad_get_parent (pad));
- GstStructure *s;
+ GstVideoFormat format;
gint w, h;
- gboolean res = FALSE;
- g_mutex_lock (tiger->mutex);
+ GST_KATE_TIGER_MUTEX_LOCK (tiger);
- s = gst_caps_get_structure (caps, 0);
+ /* Cairo expects ARGB in native endianness, and that's what we get
+ as we've forced it in the caps. We might allow swapped red/blue
+ at some point, and get tiger to swap, to make some cases faster */
+ tiger->swap_rgb = FALSE;
- if (G_LIKELY (gst_structure_get_int (s, "width", &w))
- && G_LIKELY (gst_structure_get_int (s, "height", &h))) {
- GST_INFO_OBJECT (tiger, "video sink: %d %d", w, h);
+ if (gst_video_format_parse_caps (caps, &format, &w, &h)) {
tiger->video_width = w;
tiger->video_height = h;
- res = TRUE;
}
- g_mutex_unlock (tiger->mutex);
+ GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
+
+ gst_pad_set_caps (tiger->srcpad, caps);
gst_object_unref (tiger);
return TRUE;
}
+static gdouble
+gst_kate_tiger_get_time (GstKateTiger * tiger)
+{
+ return gst_segment_to_running_time (&tiger->video_segment, GST_FORMAT_TIME,
+ tiger->video_segment.last_stop) / (gdouble) GST_SECOND;
+}
+
static GstFlowReturn
gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf)
{
@@ -599,10 +639,22 @@ gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf)
unsigned char *ptr;
int ret;
- g_mutex_lock (tiger->mutex);
+ GST_KATE_TIGER_MUTEX_LOCK (tiger);
GST_LOG_OBJECT (tiger, "got video frame, %u bytes", GST_BUFFER_SIZE (buf));
+ if (G_UNLIKELY (tiger->video_flushing)) {
+ GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
+ gst_object_unref (tiger);
+ gst_buffer_unref (buf);
+ return GST_FLOW_WRONG_STATE;
+ }
+
+ if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) {
+ gst_segment_set_last_stop (&tiger->video_segment, GST_FORMAT_TIME,
+ GST_BUFFER_TIMESTAMP (buf));
+ }
+
/* draw on it */
buf = gst_buffer_make_writable (buf);
if (G_UNLIKELY (!buf)) {
@@ -613,12 +665,17 @@ gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf)
GST_WARNING_OBJECT (tiger,
"Failed to get a pointer to video buffer data");
} else {
- ret = tiger_renderer_set_buffer (tiger->tr, ptr, tiger->video_width, tiger->video_height, tiger->video_width * 4, 0); // TODO: stride ?
+ ret =
+ tiger_renderer_set_buffer (tiger->tr, ptr, tiger->video_width,
+ tiger->video_height, tiger->video_width * 4, tiger->swap_rgb);
if (G_UNLIKELY (ret < 0)) {
GST_WARNING_OBJECT (tiger,
"Tiger renderer failed to set buffer to video frame: %d", ret);
} else {
- kate_float t = GST_BUFFER_TIMESTAMP (buf) / (gdouble) GST_SECOND;
+ kate_float t = gst_kate_tiger_get_time (tiger);
+ GST_LOG_OBJECT (tiger, "Video segment calc: last stop %ld, time %.3f",
+ (long) tiger->video_segment.last_stop, t);
+
ret = tiger_renderer_update (tiger->tr, t, 1);
if (G_UNLIKELY (ret < 0)) {
GST_WARNING_OBJECT (tiger, "Tiger renderer failed to update: %d",
@@ -636,12 +693,13 @@ gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf)
}
}
}
+
+ GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
+
rflow = gst_pad_push (tiger->srcpad, buf);
gst_object_unref (tiger);
- g_mutex_unlock (tiger->mutex);
-
return rflow;
}
@@ -654,12 +712,14 @@ gst_kate_tiger_change_state (GstElement * element, GstStateChange transition)
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY:
GST_DEBUG_OBJECT (tiger, "PAUSED -> READY, clearing kate state");
- g_mutex_lock (tiger->mutex);
+ GST_KATE_TIGER_MUTEX_LOCK (tiger);
if (tiger->tr) {
tiger_renderer_destroy (tiger->tr);
tiger->tr = NULL;
}
- g_mutex_unlock (tiger->mutex);
+ gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED);
+ tiger->video_flushing = TRUE;
+ GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
break;
default:
break;
@@ -672,7 +732,7 @@ gst_kate_tiger_change_state (GstElement * element, GstStateChange transition)
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:
GST_DEBUG_OBJECT (tiger, "READY -> PAUSED, initializing kate state");
- g_mutex_lock (tiger->mutex);
+ GST_KATE_TIGER_MUTEX_LOCK (tiger);
if (tiger->decoder.initialized) {
int ret = tiger_renderer_create (&tiger->tr);
if (ret < 0) {
@@ -692,7 +752,9 @@ gst_kate_tiger_change_state (GstElement * element, GstStateChange transition)
gst_kate_tiger_update_quality (tiger);
}
}
- g_mutex_unlock (tiger->mutex);
+ gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED);
+ tiger->video_flushing = FALSE;
+ GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
break;
default:
break;
@@ -713,18 +775,42 @@ gst_kate_tiger_seek (GstKateTiger * tiger, GstPad * pad, GstEvent * event)
gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
&stop_type, &stop);
+ GST_KATE_TIGER_MUTEX_LOCK (tiger);
+ tiger->video_flushing = TRUE;
+ gst_kate_util_decoder_base_set_flushing (&tiger->decoder, TRUE);
+ GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
+
+ if (format == GST_FORMAT_TIME) {
+ /* if seeking in time, we can update tiger to remove any appropriate events */
+ kate_float target;
+ switch (cur_type) {
+ case GST_SEEK_TYPE_SET:
+ target = cur / (float) GST_SECOND;
+ break;
+ case GST_SEEK_TYPE_CUR:
+ target = gst_kate_tiger_get_time (tiger) + cur / (float) GST_SECOND;
+ break;
+ case GST_SEEK_TYPE_END:
+ GST_WARNING_OBJECT (tiger,
+ "Seeking from the end, cannot work out target so flushing everything");
+ target = (kate_float) 0;
+ break;
+ default:
+ GST_WARNING_OBJECT (tiger, "Unexpected seek type");
+ target = (kate_float) 0;
+ break;
+ }
+ GST_INFO_OBJECT (tiger, "Seeking in time to %f", target);
+ GST_KATE_TIGER_MUTEX_LOCK (tiger);
+ tiger_renderer_seek (tiger->tr, target);
+ GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
+ }
+
/* forward to both sinks */
gst_event_ref (event);
if (gst_pad_push_event (tiger->videosinkpad, event)) {
- if (gst_pad_push_event (tiger->katesinkpad, event)) {
- if (format == GST_FORMAT_TIME) {
- /* if seeking in time, we can update tiger to remove any appropriate events */
- kate_float target = cur / (gdouble) GST_SECOND;
- GST_INFO_OBJECT (tiger, "Seeking in time to %f", target);
- g_mutex_lock (tiger->mutex);
- tiger_renderer_seek (tiger->tr, target);
- g_mutex_unlock (tiger->mutex);
- }
+ int ret = gst_pad_push_event (tiger->katesinkpad, event);
+ if (ret) {
return TRUE;
} else {
return FALSE;
@@ -744,6 +830,9 @@ gst_kate_tiger_source_event (GstPad * pad, GstEvent * event)
g_return_val_if_fail (tiger != NULL, FALSE);
+ GST_LOG_OBJECT (tiger, "Event on source pad: %s",
+ GST_EVENT_TYPE_NAME (event));
+
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_SEEK:
GST_INFO_OBJECT (tiger, "Seek on source pad");
@@ -760,17 +849,30 @@ gst_kate_tiger_source_event (GstPad * pad, GstEvent * event)
}
static gboolean
-gst_kate_tiger_kate_event (GstPad * pad, GstEvent * event)
+gst_kate_tiger_handle_kate_event (GstPad * pad, GstEvent * event)
{
GstKateTiger *tiger =
(GstKateTiger *) (gst_object_get_parent (GST_OBJECT (pad)));
gboolean res = TRUE;
- g_return_val_if_fail (tiger != NULL, FALSE);
-
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_NEWSEGMENT:
GST_INFO_OBJECT (tiger, "New segment on Kate pad");
+ GST_KATE_TIGER_MUTEX_LOCK (tiger);
+ gst_kate_util_decoder_base_new_segment_event (&tiger->decoder, event);
+ GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
+ gst_event_unref (event);
+ break;
+ case GST_EVENT_FLUSH_START:
+ GST_KATE_TIGER_MUTEX_LOCK (tiger);
+ gst_kate_util_decoder_base_set_flushing (&tiger->decoder, TRUE);
+ GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
+ gst_event_unref (event);
+ break;
+ case GST_EVENT_FLUSH_STOP:
+ GST_KATE_TIGER_MUTEX_LOCK (tiger);
+ gst_kate_util_decoder_base_set_flushing (&tiger->decoder, FALSE);
+ GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
gst_event_unref (event);
break;
case GST_EVENT_EOS:
@@ -789,12 +891,115 @@ gst_kate_tiger_kate_event (GstPad * pad, GstEvent * event)
return res;
}
+static gboolean
+gst_kate_tiger_kate_event (GstPad * pad, GstEvent * event)
+{
+ GstKateTiger *tiger =
+ (GstKateTiger *) (gst_object_get_parent (GST_OBJECT (pad)));
+ gboolean res = TRUE;
+
+ g_return_val_if_fail (tiger != NULL, FALSE);
+
+ GST_LOG_OBJECT (tiger, "Event on Kate pad: %s", GST_EVENT_TYPE_NAME (event));
+
+ /* Delay events till we've set caps */
+ if (gst_kate_util_decoder_base_queue_event (&tiger->decoder, event,
+ &gst_kate_tiger_handle_kate_event, pad)) {
+ gst_object_unref (tiger);
+ return TRUE;
+ }
+
+ res = gst_kate_tiger_handle_kate_event (pad, event);
+
+ gst_object_unref (tiger);
+
+ return res;
+}
+
+static gboolean
+gst_kate_tiger_handle_video_event (GstPad * pad, GstEvent * event)
+{
+ GstKateTiger *tiger =
+ (GstKateTiger *) (gst_object_get_parent (GST_OBJECT (pad)));
+ gboolean res = TRUE;
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_NEWSEGMENT:
+ {
+ gboolean update;
+ gdouble rate, arate;
+ GstFormat format;
+ gint64 start, stop, time;
+
+ gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
+ &start, &stop, &time);
+
+ if (format == GST_FORMAT_TIME) {
+ GST_DEBUG_OBJECT (tiger, "video pad segment:"
+ " Update %d, rate %g arate %g format %d start %" GST_TIME_FORMAT
+ " %" GST_TIME_FORMAT " position %" GST_TIME_FORMAT,
+ update, rate, arate, format, GST_TIME_ARGS (start),
+ GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
+
+ GST_KATE_TIGER_MUTEX_LOCK (tiger);
+ gst_segment_set_newsegment_full (&tiger->video_segment, update, rate,
+ arate, format, start, stop, time);
+ GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
+ }
+
+ res = gst_pad_event_default (pad, event);
+ break;
+ }
+ case GST_EVENT_FLUSH_START:
+ GST_KATE_TIGER_MUTEX_LOCK (tiger);
+ gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED);
+ tiger->video_flushing = TRUE;
+ GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
+ res = gst_pad_event_default (pad, event);
+ break;
+ case GST_EVENT_FLUSH_STOP:
+ GST_KATE_TIGER_MUTEX_LOCK (tiger);
+ gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED);
+ tiger->video_flushing = FALSE;
+ GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
+ res = gst_pad_event_default (pad, event);
+ break;
+ default:
+ res = gst_pad_event_default (pad, event);
+ break;
+ }
+
+ gst_object_unref (tiger);
+
+ return res;
+}
+
+static gboolean
+gst_kate_tiger_video_event (GstPad * pad, GstEvent * event)
+{
+ GstKateTiger *tiger =
+ (GstKateTiger *) (gst_object_get_parent (GST_OBJECT (pad)));
+ gboolean res = TRUE;
+
+ g_return_val_if_fail (tiger != NULL, FALSE);
+
+ GST_INFO_OBJECT (tiger, "Event on video pad: %s",
+ GST_EVENT_TYPE_NAME (event));
+
+ res = gst_kate_tiger_handle_video_event (pad, event);
+
+ gst_object_unref (tiger);
+
+ return res;
+}
+
gboolean
gst_kate_tiger_kate_sink_query (GstPad * pad, GstQuery * query)
{
GstKateTiger *tiger = GST_KATE_TIGER (gst_pad_get_parent (pad));
gboolean res = gst_kate_decoder_base_sink_query (&tiger->decoder,
GST_ELEMENT_CAST (tiger), pad, query);
+ GST_INFO_OBJECT (tiger, "Query on Kate pad");
gst_object_unref (tiger);
return res;
}
diff --git a/ext/kate/gstkatetiger.h b/ext/kate/gstkatetiger.h
index 0ab7dc136..353f9f79e 100644
--- a/ext/kate/gstkatetiger.h
+++ b/ext/kate/gstkatetiger.h
@@ -68,14 +68,12 @@ typedef struct _GstKateTigerClass GstKateTigerClass;
struct _GstKateTiger
{
- GstElement element;
+ GstKateDecoderBase decoder;
GstPad *katesinkpad;
GstPad *videosinkpad;
GstPad *srcpad;
- GstKateDecoderBase decoder;
-
tiger_renderer *tr;
gdouble quality;
@@ -93,8 +91,12 @@ struct _GstKateTiger
gint video_width;
gint video_height;
+ gboolean swap_rgb;
GMutex *mutex;
+
+ GstSegment video_segment;
+ gboolean video_flushing;
};
struct _GstKateTigerClass
diff --git a/ext/kate/gstkateutil.c b/ext/kate/gstkateutil.c
index 5b71b94a3..0bccc4b6f 100644
--- a/ext/kate/gstkateutil.c
+++ b/ext/kate/gstkateutil.c
@@ -23,10 +23,17 @@
# include "config.h"
#endif
+#include <string.h>
#include <gst/tag/tag.h>
#include "gstkate.h"
#include "gstkateutil.h"
+GST_DEBUG_CATEGORY_EXTERN (gst_kateutil_debug);
+#define GST_CAT_DEFAULT gst_kateutil_debug
+
+static void gst_kate_util_decoder_base_free_event_queue (GstKateDecoderBase *
+ decoder);
+
GstCaps *
gst_kate_util_set_header_on_caps (GstElement * element, GstCaps * caps,
GList * headers)
@@ -95,7 +102,8 @@ gst_kate_util_install_decoder_base_properties (GObjectClass * gobject_class)
}
void
-gst_kate_util_decode_base_init (GstKateDecoderBase * decoder)
+gst_kate_util_decode_base_init (GstKateDecoderBase * decoder,
+ gboolean delay_events)
{
if (G_UNLIKELY (!decoder))
return;
@@ -106,6 +114,8 @@ gst_kate_util_decode_base_init (GstKateDecoderBase * decoder)
decoder->original_canvas_height = 0;
decoder->tags = NULL;
decoder->initialized = FALSE;
+ decoder->delay_events = delay_events;
+ decoder->event_queue = NULL;
}
static void
@@ -121,10 +131,77 @@ gst_kate_util_decode_base_reset (GstKateDecoderBase * decoder)
}
decoder->original_canvas_width = 0;
decoder->original_canvas_height = 0;
+ if (decoder->event_queue) {
+ gst_kate_util_decoder_base_free_event_queue (decoder);
+ }
decoder->initialized = FALSE;
}
gboolean
+gst_kate_util_decoder_base_queue_event (GstKateDecoderBase * decoder,
+ GstEvent * event, gboolean (*handler) (GstPad *, GstEvent *), GstPad * pad)
+{
+ gboolean can_be_queued;
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_FLUSH_START:
+ case GST_EVENT_FLUSH_STOP:
+ case GST_EVENT_EOS:
+ can_be_queued = FALSE;
+ break;
+ default:
+ can_be_queued = TRUE;
+ break;
+ }
+
+ if (decoder->delay_events && can_be_queued) {
+ GstKateDecoderBaseQueuedEvent *item;
+ GST_DEBUG_OBJECT (decoder, "We have to delay the event");
+ item = g_slice_new (GstKateDecoderBaseQueuedEvent);
+ if (item) {
+ item->event = event;
+ item->pad = pad;
+ item->handler = handler;
+ g_queue_push_tail (decoder->event_queue, item);
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
+}
+
+static void
+gst_kate_util_decoder_base_free_event_queue (GstKateDecoderBase * decoder)
+{
+ while (decoder->event_queue->length) {
+ GstKateDecoderBaseQueuedEvent *item = (GstKateDecoderBaseQueuedEvent *)
+ g_queue_pop_head (decoder->event_queue);
+ g_slice_free (GstKateDecoderBaseQueuedEvent, item);
+ }
+ g_queue_free (decoder->event_queue);
+ decoder->event_queue = NULL;
+}
+
+static void
+gst_kate_util_decoder_base_drain_event_queue (GstKateDecoderBase * decoder)
+{
+ decoder->delay_events = FALSE;
+
+ if (decoder->event_queue->length == 0)
+ return;
+
+ GST_DEBUG_OBJECT (decoder, "We can now drain all events!");
+ while (decoder->event_queue->length) {
+ GstKateDecoderBaseQueuedEvent *item = (GstKateDecoderBaseQueuedEvent *)
+ g_queue_pop_head (decoder->event_queue);
+ (*item->handler) (item->pad, item->event);
+ g_slice_free (GstKateDecoderBaseQueuedEvent, item);
+ }
+}
+
+gboolean
gst_kate_util_decoder_base_get_property (GstKateDecoderBase * decoder,
GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
{
@@ -152,38 +229,67 @@ gst_kate_util_decoder_base_get_property (GstKateDecoderBase * decoder,
GstFlowReturn
gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
GstElement * element, GstPad * pad, GstBuffer * buf, GstPad * srcpad,
- const kate_event ** ev)
+ GstPad * tagpad, GstCaps ** src_caps, const kate_event ** ev)
{
kate_packet kp;
int ret;
GstFlowReturn rflow = GST_FLOW_OK;
+ gboolean is_header;
GST_DEBUG_OBJECT (element, "got kate packet, %u bytes, type %02x",
GST_BUFFER_SIZE (buf),
GST_BUFFER_SIZE (buf) == 0 ? -1 : GST_BUFFER_DATA (buf)[0]);
+
+ is_header = GST_BUFFER_SIZE (buf) > 0 && (GST_BUFFER_DATA (buf)[0] & 0x80);
+
+ if (!is_header && decoder->tags) {
+ /* after we've processed headers, send any tags before processing the data packet */
+ GST_DEBUG_OBJECT (element, "Not a header, sending tags for pad %s:%s",
+ GST_DEBUG_PAD_NAME (tagpad));
+ gst_element_found_tags_for_pad (element, tagpad, decoder->tags);
+ decoder->tags = NULL;
+ }
+
kate_packet_wrap (&kp, GST_BUFFER_SIZE (buf), GST_BUFFER_DATA (buf));
ret = kate_high_decode_packetin (&decoder->k, &kp, ev);
if (G_UNLIKELY (ret < 0)) {
GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL),
("Failed to decode Kate packet: %d", ret));
return GST_FLOW_ERROR;
- } else if (G_UNLIKELY (ret > 0)) {
+ }
+
+ if (G_UNLIKELY (ret > 0)) {
GST_DEBUG_OBJECT (element,
"kate_high_decode_packetin has received EOS packet");
- return GST_FLOW_OK;
}
/* headers may be interesting to retrieve information from */
- if (G_LIKELY (GST_BUFFER_SIZE (buf) > 0))
+ if (G_UNLIKELY (is_header)) {
switch (GST_BUFFER_DATA (buf)[0]) {
- GstCaps *caps;
-
case 0x80: /* ID header */
GST_INFO_OBJECT (element, "Parsed ID header: language %s, category %s",
decoder->k.ki->language, decoder->k.ki->category);
- caps = gst_caps_new_simple ("text/x-pango-markup", NULL);
- gst_pad_set_caps (srcpad, caps);
- gst_caps_unref (caps);
+ if (src_caps) {
+ if (*src_caps) {
+ gst_caps_unref (*src_caps);
+ *src_caps = NULL;
+ }
+ if (strcmp (decoder->k.ki->category, "K-SPU") == 0 ||
+ strcmp (decoder->k.ki->category, "spu-subtitles") == 0) {
+ *src_caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL);
+ } else if (decoder->k.ki->text_markup_type == kate_markup_none) {
+ *src_caps = gst_caps_new_simple ("text/plain", NULL);
+ } else {
+ *src_caps = gst_caps_new_simple ("text/x-pango-markup", NULL);
+ }
+ GST_INFO_OBJECT (element, "Setting src caps to %s",
+ gst_caps_to_string (*src_caps));
+ if (!gst_pad_set_caps (srcpad, *src_caps)) {
+ GST_ERROR_OBJECT (element,
+ "Failed to renegotiate caps for pad %s:%s",
+ GST_DEBUG_PAD_NAME (srcpad));
+ }
+ }
if (decoder->k.ki->language && *decoder->k.ki->language) {
GstTagList *old = decoder->tags, *tags = gst_tag_list_new ();
if (tags) {
@@ -214,6 +320,9 @@ gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
decoder->original_canvas_width = decoder->k.ki->original_canvas_width;
decoder->original_canvas_height = decoder->k.ki->original_canvas_height;
+ /* we can now send away any event we've delayed, as the src pad now has caps */
+ gst_kate_util_decoder_base_drain_event_queue (decoder);
+
break;
case 0x81: /* Vorbis comments header */
@@ -247,8 +356,9 @@ gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
if (old)
gst_tag_list_free (old);
+#if 0
if (decoder->initialized) {
- gst_element_found_tags_for_pad (element, srcpad, decoder->tags);
+ gst_element_found_tags_for_pad (element, tagpad, decoder->tags);
decoder->tags = NULL;
} else {
/* Only push them as messages for the time being. *
@@ -257,12 +367,14 @@ gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
gst_message_new_tag (GST_OBJECT (element),
gst_tag_list_copy (decoder->tags)));
}
+#endif
}
break;
default:
break;
}
+ }
return rflow;
}
@@ -285,7 +397,10 @@ gst_kate_decoder_base_change_state (GstKateDecoderBase * decoder,
GST_WARNING_OBJECT (element, "failed to initialize kate state: %d",
ret);
}
+ gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED);
+ decoder->kate_flushing = FALSE;
decoder->initialized = TRUE;
+ decoder->event_queue = g_queue_new ();
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
break;
@@ -304,6 +419,8 @@ gst_kate_decoder_base_change_state (GstKateDecoderBase * decoder,
kate_high_decode_clear (&decoder->k);
decoder->initialized = FALSE;
}
+ gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED);
+ decoder->kate_flushing = TRUE;
gst_kate_util_decode_base_reset (decoder);
break;
case GST_STATE_CHANGE_READY_TO_NULL:
@@ -316,6 +433,73 @@ gst_kate_decoder_base_change_state (GstKateDecoderBase * decoder,
return res;
}
+void
+gst_kate_util_decoder_base_set_flushing (GstKateDecoderBase * decoder,
+ gboolean flushing)
+{
+ decoder->kate_flushing = flushing;
+ gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED);
+}
+
+void
+gst_kate_util_decoder_base_new_segment_event (GstKateDecoderBase * decoder,
+ GstEvent * event)
+{
+ gboolean update;
+ gdouble rate;
+ GstFormat format;
+ gint64 start, stop, time;
+ gdouble arate;
+
+ gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
+ &start, &stop, &time);
+ GST_DEBUG_OBJECT (decoder, "kate pad segment:"
+ " Update %d, rate %g arate %g format %d start %" GST_TIME_FORMAT
+ " %" GST_TIME_FORMAT " position %" GST_TIME_FORMAT,
+ update, rate, arate, format, GST_TIME_ARGS (start),
+ GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
+ gst_segment_set_newsegment_full (&decoder->kate_segment, update, rate,
+ arate, format, start, stop, time);
+}
+
+gboolean
+gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder,
+ GstElement * element, GstBuffer * buf)
+{
+ gint64 clip_start = 0, clip_stop = 0;
+ gboolean in_seg;
+
+ if (decoder->kate_flushing) {
+ GST_LOG_OBJECT (element, "Kate pad flushing, buffer ignored");
+ return FALSE;
+ }
+
+ if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) {
+ GstClockTime stop;
+
+ if (G_LIKELY (GST_BUFFER_DURATION_IS_VALID (buf)))
+ stop = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);
+ else
+ stop = GST_CLOCK_TIME_NONE;
+
+ in_seg = gst_segment_clip (&decoder->kate_segment, GST_FORMAT_TIME,
+ GST_BUFFER_TIMESTAMP (buf), stop, &clip_start, &clip_stop);
+ } else {
+ in_seg = TRUE;
+ }
+
+ if (in_seg) {
+ if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
+ gst_segment_set_last_stop (&decoder->kate_segment, GST_FORMAT_TIME,
+ clip_start);
+ }
+ } else {
+ GST_INFO_OBJECT (element, "Kate buffer not in segment, ignored");
+ }
+
+ return in_seg;
+}
+
static GstClockTime
gst_kate_util_granule_time (kate_state * k, gint64 granulepos)
{
diff --git a/ext/kate/gstkateutil.h b/ext/kate/gstkateutil.h
index 6e8ea2e01..27b6f70f3 100644
--- a/ext/kate/gstkateutil.h
+++ b/ext/kate/gstkateutil.h
@@ -37,6 +37,15 @@ G_BEGIN_DECLS enum
typedef struct
{
+ GstEvent * event;
+ gboolean (*handler)(GstPad *, GstEvent *);
+ GstPad *pad;
+} GstKateDecoderBaseQueuedEvent;
+
+typedef struct
+{
+ GstElement element;
+
kate_state k;
gboolean initialized;
@@ -49,11 +58,17 @@ typedef struct
gint original_canvas_width;
gint original_canvas_height;
+ GstSegment kate_segment;
+ gboolean kate_flushing;
+
+ gboolean delay_events;
+ GQueue *event_queue;
} GstKateDecoderBase;
extern GstCaps *gst_kate_util_set_header_on_caps (GstElement * element,
GstCaps * caps, GList * headers);
-extern void gst_kate_util_decode_base_init (GstKateDecoderBase * decoder);
+extern void gst_kate_util_decode_base_init (GstKateDecoderBase * decoder,
+ gboolean delay_events);
extern void gst_kate_util_install_decoder_base_properties (GObjectClass *
gobject_class);
extern gboolean gst_kate_util_decoder_base_get_property (GstKateDecoderBase *
@@ -62,7 +77,16 @@ extern gboolean gst_kate_util_decoder_base_get_property (GstKateDecoderBase *
extern GstFlowReturn
gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
GstElement * element, GstPad * pad, GstBuffer * buffer, GstPad * srcpad,
- const kate_event ** ev);
+ GstPad * tagpad, GstCaps **src_caps, const kate_event ** ev);
+extern void
+gst_kate_util_decoder_base_set_flushing (GstKateDecoderBase * decoder,
+ gboolean flushing);
+extern void
+gst_kate_util_decoder_base_new_segment_event (GstKateDecoderBase * decoder,
+ GstEvent * event);
+extern gboolean
+gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder,
+ GstElement * element, GstBuffer * buf);
extern GstStateChangeReturn
gst_kate_decoder_base_change_state (GstKateDecoderBase * decoder,
GstElement * element, GstElementClass * parent_class,
@@ -72,6 +96,8 @@ extern gboolean gst_kate_decoder_base_convert (GstKateDecoderBase * decoder,
GstFormat * dest_fmt, gint64 * dest_val);
extern gboolean gst_kate_decoder_base_sink_query (GstKateDecoderBase * decoder,
GstElement * element, GstPad * pad, GstQuery * query);
+extern gboolean
+gst_kate_util_decoder_base_queue_event (GstKateDecoderBase * decoder, GstEvent * event, gboolean (*handler)(GstPad *, GstEvent *), GstPad * pad);
G_END_DECLS
#endif /* __GST_KATE_UTIL_H__ */