diff options
author | Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com> | 2010-01-25 18:58:38 +0000 |
---|---|---|
committer | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2010-12-25 16:59:22 +0100 |
commit | 8574e8f991f68506af3a0c369c933020688bd4c3 (patch) | |
tree | 955321ae9406e1fe7ac6c8155bf561f7a6e65d35 /ext/kate/gstkatetiger.c | |
parent | 4422cca1d3f98fcc68895e9a051f38dc22d4f7d7 (diff) |
kate: add segment tracking, and various other improvements
https://bugzilla.gnome.org/show_bug.cgi?id=600929
Diffstat (limited to 'ext/kate/gstkatetiger.c')
-rw-r--r-- | ext/kate/gstkatetiger.c | 321 |
1 files changed, 263 insertions, 58 deletions
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; } |