From 1ae52725d92a3781dd605526d5f8e75bdebe337d Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Thu, 30 Apr 2009 13:45:30 +0300 Subject: [PATCH 1/4] fpsdisplay: code cleanup and plug overlay as needed Pluggin the text-ovelay causes some slowdowns and might need a colorspace converter. We now only check the text-overlay property whne goint to ready and plug or unplug the text-overlay at that time. If the property changes during playing, its not switched immediately. --- gst/debugutils/fpsdisplaysink.c | 85 ++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 28 deletions(-) diff --git a/gst/debugutils/fpsdisplaysink.c b/gst/debugutils/fpsdisplaysink.c index 5819a3d13a..22568fe6c3 100644 --- a/gst/debugutils/fpsdisplaysink.c +++ b/gst/debugutils/fpsdisplaysink.c @@ -76,6 +76,7 @@ struct _FPSDisplaySinkPrivate GstElement *text_overlay; GstElement *video_sink; GstQuery *query; + GstPad *ghost_pad; /* statistics */ guint64 frames_rendered, last_frames_rendered; @@ -122,12 +123,14 @@ fps_display_sink_class_init (FPSDisplaySinkClass * klass) g_object_class_install_property (gobject_klass, ARG_SYNC, g_param_spec_boolean ("sync", - "Sync", "Sync on the clock", FALSE, G_PARAM_READWRITE)); + "Sync", "Sync on the clock", TRUE, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE)); g_object_class_install_property (gobject_klass, ARG_TEXT_OVERLAY, g_param_spec_boolean ("text-overlay", "text-overlay", - "Wether to use text-overlay", TRUE, G_PARAM_READWRITE)); + "Wether to use text-overlay", TRUE, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE)); gstelement_klass->change_state = fps_display_sink_change_state; @@ -186,7 +189,7 @@ on_video_sink_data_flow (GstPad * pad, GstMiniObject * mini_obj, static void fps_display_sink_init (FPSDisplaySink * self, FPSDisplaySinkClass * g_class) { - GstPad *sink_pad, *target_pad; + GstPad *sink_pad; self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, FPS_TYPE_DISPLAY_SINK, FPSDisplaySinkPrivate); @@ -197,39 +200,27 @@ fps_display_sink_init (FPSDisplaySink * self, FPSDisplaySinkClass * g_class) /* create child elements */ self->priv->video_sink = gst_element_factory_make ("xvimagesink", "fps-display-video_sink"); - self->priv->text_overlay = - gst_element_factory_make ("textoverlay", "fps-display-text-overlay"); - - if (!self->priv->video_sink || !self->priv->text_overlay) { + if (!self->priv->video_sink) { GST_ERROR_OBJECT (self, "element could not be created"); return; } g_object_set (self->priv->video_sink, "sync", self->priv->sync, NULL); - g_object_set (self->priv->text_overlay, "font-desc", DEFAULT_FONT, NULL); /* take a ref before bin takes the ownership */ - gst_object_ref (self->priv->text_overlay); gst_object_ref (self->priv->video_sink); - gst_bin_add_many (GST_BIN (self), - self->priv->text_overlay, self->priv->video_sink, NULL); - - if (!gst_element_link (self->priv->text_overlay, self->priv->video_sink)) { - GST_ERROR_OBJECT (self, "Could not link elements"); - } + gst_bin_add (GST_BIN (self), self->priv->video_sink); /* create ghost pad */ - target_pad = - gst_element_get_static_pad (self->priv->text_overlay, "video_sink"); - sink_pad = gst_ghost_pad_new ("sink_pad", target_pad); - gst_object_unref (target_pad); - gst_element_add_pad (GST_ELEMENT (self), sink_pad); + self->priv->ghost_pad = + gst_ghost_pad_new_no_target ("sink_pad", GST_PAD_SINK); + gst_element_add_pad (GST_ELEMENT (self), self->priv->ghost_pad); + /* attach or pad probe */ sink_pad = gst_element_get_static_pad (self->priv->video_sink, "sink"); gst_pad_add_data_probe (sink_pad, G_CALLBACK (on_video_sink_data_flow), (gpointer) self); - gst_object_unref (sink_pad); self->priv->query = gst_query_new_position (GST_FORMAT_TIME); @@ -282,12 +273,48 @@ display_current_fps (gpointer data) static void fps_display_sink_start (FPSDisplaySink * self) { + GstPad *target_pad; + /* Init counters */ self->priv->next_ts = GST_CLOCK_TIME_NONE; self->priv->last_ts = GST_CLOCK_TIME_NONE; self->priv->frames_rendered = G_GUINT64_CONSTANT (0); self->priv->frames_dropped = G_GUINT64_CONSTANT (0); + GST_WARNING ("use text-overlay? %d", self->priv->use_text_overlay); + + if (self->priv->use_text_overlay) { + if (!self->priv->text_overlay) { + self->priv->text_overlay = + gst_element_factory_make ("textoverlay", "fps-display-text-overlay"); + if (!self->priv->text_overlay) { + GST_WARNING_OBJECT (self, "text-overlay element could not be created"); + self->priv->use_text_overlay = FALSE; + goto no_text_overlay; + } + gst_object_ref (self->priv->text_overlay); + g_object_set (self->priv->text_overlay, + "font-desc", DEFAULT_FONT, "silent", FALSE, NULL); + } + gst_bin_add (GST_BIN (self), self->priv->text_overlay); + + if (!gst_element_link (self->priv->text_overlay, self->priv->video_sink)) { + GST_ERROR_OBJECT (self, "Could not link elements"); + } + target_pad = + gst_element_get_static_pad (self->priv->text_overlay, "video_sink"); + } +no_text_overlay: + if (!self->priv->use_text_overlay) { + if (self->priv->text_overlay) { + gst_element_unlink (self->priv->text_overlay, self->priv->video_sink); + gst_bin_remove (GST_BIN (self), self->priv->text_overlay); + } + target_pad = gst_element_get_static_pad (self->priv->video_sink, "sink"); + } + gst_ghost_pad_set_target (GST_GHOST_PAD (self->priv->ghost_pad), target_pad); + gst_object_unref (target_pad); + /* Set a timeout for the fps display */ self->priv->timeout_id = g_timeout_add (FPS_DISPLAY_INTERVAL_MS, @@ -341,13 +368,15 @@ fps_display_sink_set_property (GObject * object, guint prop_id, case ARG_TEXT_OVERLAY: self->priv->use_text_overlay = g_value_get_boolean (value); - if (!(self->priv->use_text_overlay)) { - GST_DEBUG_OBJECT (self, "text-overlay set to false"); - g_object_set (self->priv->text_overlay, "text", "", "silent", TRUE, - NULL); - } else { - GST_DEBUG_OBJECT (self, "text-overlay set to true"); - g_object_set (self->priv->text_overlay, "silent", FALSE, NULL); + if (self->priv->text_overlay) { + if (!self->priv->use_text_overlay) { + GST_DEBUG_OBJECT (self, "text-overlay set to false"); + g_object_set (self->priv->text_overlay, "text", "", "silent", TRUE, + NULL); + } else { + GST_DEBUG_OBJECT (self, "text-overlay set to true"); + g_object_set (self->priv->text_overlay, "silent", FALSE, NULL); + } } break; default: From f38cb76b5f2db479ab488bc1de2b53b5700f984a Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 30 Apr 2009 14:18:58 +0200 Subject: [PATCH 2/4] dvdspu: don't EOS when the subtitle got EOS Don't forward the EOS on the subtitle pad as the video might still be running. --- gst/dvdspu/gstdvdspu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gst/dvdspu/gstdvdspu.c b/gst/dvdspu/gstdvdspu.c index 6ad8ed0687..3b4c1a0c2e 100644 --- a/gst/dvdspu/gstdvdspu.c +++ b/gst/dvdspu/gstdvdspu.c @@ -1366,6 +1366,12 @@ gst_dvd_spu_subpic_event (GstPad * pad, GstEvent * event) /* We don't forward flushes on the spu pad */ gst_event_unref (event); goto done; + case GST_EVENT_EOS: + /* drop EOS on the subtitle pad, it means there are no more subtitles, + * video might still continue, though */ + gst_event_unref (event); + goto done; + break; default: res = gst_pad_event_default (pad, event); break; From 5704bc8f89c745a86dbe435a2e2c008c499e8132 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 30 Apr 2009 14:20:16 +0200 Subject: [PATCH 3/4] dvdspu: do some basic clipping Add some basic clipping of the subtitle region when the subtitle is bigger than the image we should put it on. --- gst/dvdspu/gstdvdspu-render.c | 66 ++++++++++++++++++++++++++++------- gst/dvdspu/gstdvdspu.h | 1 + 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/gst/dvdspu/gstdvdspu-render.c b/gst/dvdspu/gstdvdspu-render.c index 23a6a08531..e3bae8b61a 100644 --- a/gst/dvdspu/gstdvdspu-render.c +++ b/gst/dvdspu/gstdvdspu-render.c @@ -416,13 +416,7 @@ gst_dvd_spu_render_spu (GstDVDSpu * dvdspu, GstBuffer * buf) state->hl_rect.left, state->hl_rect.top, state->hl_rect.right, state->hl_rect.bottom); - /* We start rendering from the first line of the display rect */ - y = state->disp_rect.top; - - /* Update our plane references to the first line of the disp_rect */ - planes[0] += state->Y_stride * y; - planes[1] += state->UV_stride * (y / 2); - planes[2] += state->UV_stride * (y / 2); + GST_DEBUG ("vid_disp %d,%d", state->vid_width, state->vid_height); /* When reading RLE data, we track the offset in nibbles... */ state->cur_offsets[0] = state->pix_data[0] * 2; @@ -442,18 +436,62 @@ gst_dvd_spu_render_spu (GstDVDSpu * dvdspu, GstBuffer * buf) } else state->cur_chg_col = NULL; + /* We start rendering from the first line of the display rect */ + y = state->disp_rect.top; /* start_y is always an even number and we render lines in pairs from there, * accumulating 2 lines of chroma then blending it. We might need to render a * single line at the end if the display rect ends on an even line too. */ last_y = (state->disp_rect.bottom - 1) & ~(0x01); + + /* center the image when display rectangle exceeds the video width */ + if (state->vid_width < state->disp_rect.right) { + gint diff, disp_width; + + disp_width = state->disp_rect.left - state->disp_rect.right; + diff = (disp_width - state->vid_width) / 2; + + /* fixme, this is not used yet */ + state->clip_rect.left = state->disp_rect.left + diff; + state->clip_rect.right = state->disp_rect.right - diff; + + GST_DEBUG ("clipping width to %d,%d", state->clip_rect.left, + state->clip_rect.right); + } else { + state->clip_rect.left = state->disp_rect.left; + state->clip_rect.right = state->disp_rect.right; + } + + /* for the height, chop off the bottom bits of the diplay rectangle because we + * assume the picture is in the lower part. We should better check where it + * is and do something more clever. */ + state->clip_rect.bottom = state->disp_rect.bottom; + if (state->vid_height < state->disp_rect.bottom) { + state->clip_rect.top = state->disp_rect.bottom - state->vid_height; + GST_DEBUG ("clipping height to %d,%d", state->clip_rect.top, + state->clip_rect.bottom); + } else { + state->clip_rect.top = state->disp_rect.top; + /* Update our plane references to the first line of the disp_rect */ + planes[0] += state->Y_stride * y; + planes[1] += state->UV_stride * (y / 2); + planes[2] += state->UV_stride * (y / 2); + } + for (state->cur_Y = y; state->cur_Y <= last_y; state->cur_Y++) { + gboolean clip; + + clip = (state->cur_Y < state->clip_rect.top + || state->cur_Y > state->clip_rect.bottom); + /* Reset the compositing buffer */ dvdspu_clear_comp_buffers (state); /* Render even line */ state->comp_last_x_ptr = state->comp_last_x; dvdspu_render_line (state, planes, &state->cur_offsets[0]); - /* Advance the luminance output pointer */ - planes[0] += state->Y_stride; + if (!clip) { + /* Advance the luminance output pointer */ + planes[0] += state->Y_stride; + } state->cur_Y++; /* Render odd line */ @@ -462,10 +500,12 @@ gst_dvd_spu_render_spu (GstDVDSpu * dvdspu, GstBuffer * buf) /* Blend the accumulated UV compositing buffers onto the output */ dvdspu_blend_comp_buffers (state, planes); - /* Update all the output pointers */ - planes[0] += state->Y_stride; - planes[1] += state->UV_stride; - planes[2] += state->UV_stride; + if (!clip) { + /* Update all the output pointers */ + planes[0] += state->Y_stride; + planes[1] += state->UV_stride; + planes[2] += state->UV_stride; + } } if (state->cur_Y == state->disp_rect.bottom) { g_assert ((state->disp_rect.bottom & 0x01) == 0); diff --git a/gst/dvdspu/gstdvdspu.h b/gst/dvdspu/gstdvdspu.h index 0432a3af9a..dfc51f9e93 100644 --- a/gst/dvdspu/gstdvdspu.h +++ b/gst/dvdspu/gstdvdspu.h @@ -122,6 +122,7 @@ struct SpuState { GstBuffer *pix_buf; /* Current SPU packet the pix_data references */ SpuRect disp_rect; + SpuRect clip_rect; SpuRect hl_rect; guint32 current_clut[16]; /* Colour lookup table from incoming events */ From 8d4315ee5c74c5bb6bb6adf9ed5824101d9ccda1 Mon Sep 17 00:00:00 2001 From: Tristan Matthews Date: Thu, 30 Apr 2009 17:08:52 +0100 Subject: [PATCH 4/4] fpsdisplaysink: init variable to NULL to avoid compiler warning Fixes #580901. --- gst/debugutils/fpsdisplaysink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/debugutils/fpsdisplaysink.c b/gst/debugutils/fpsdisplaysink.c index 22568fe6c3..d22dfad3f5 100644 --- a/gst/debugutils/fpsdisplaysink.c +++ b/gst/debugutils/fpsdisplaysink.c @@ -273,7 +273,7 @@ display_current_fps (gpointer data) static void fps_display_sink_start (FPSDisplaySink * self) { - GstPad *target_pad; + GstPad *target_pad = NULL; /* Init counters */ self->priv->next_ts = GST_CLOCK_TIME_NONE;