Пример #1
0
static GstFlowReturn
gst_rsvg_overlay_data_sink_chain (GstPad * pad, GstBuffer * buffer)
{
  GstRsvgOverlay *overlay = GST_RSVG_OVERLAY (GST_PAD_PARENT (pad));

  gst_adapter_push (overlay->adapter, buffer);
  return GST_FLOW_OK;
}
Пример #2
0
static void
gst_rsvg_overlay_finalize (GObject * object)
{
  GstRsvgOverlay *overlay = GST_RSVG_OVERLAY (object);

  g_object_unref (overlay->adapter);

  G_OBJECT_CLASS (parent_class)->finalize (object);
}
Пример #3
0
static gboolean
gst_rsvg_overlay_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
    GstCaps * outcaps)
{
  GstRsvgOverlay *overlay = GST_RSVG_OVERLAY (btrans);

  return G_LIKELY (gst_video_format_parse_caps (incaps,
          &overlay->caps_format, &overlay->caps_width, &overlay->caps_height));
}
Пример #4
0
static gboolean
gst_rsvg_overlay_stop (GstBaseTransform * btrans)
{
  GstRsvgOverlay *overlay = GST_RSVG_OVERLAY (btrans);

  if (overlay->handle) {
    g_object_unref (overlay->handle);
    g_object_unref (overlay->adapter);
    overlay->handle = NULL;
  }

  return TRUE;
}
Пример #5
0
static void
gst_rsvg_overlay_get_property (GObject * object, guint prop_id, GValue * value,
    GParamSpec * pspec)
{
  GstRsvgOverlay *overlay = GST_RSVG_OVERLAY (object);

  switch (prop_id) {
    case PROP_X:
      g_value_set_int (value, overlay->x_offset);
      break;
    case PROP_Y:
      g_value_set_int (value, overlay->y_offset);
      break;
    case PROP_X_RELATIVE:
      g_value_set_float (value, overlay->x_relative);
      break;
    case PROP_Y_RELATIVE:
      g_value_set_float (value, overlay->y_relative);
      break;

    case PROP_WIDTH:
      g_value_set_int (value, overlay->width);
      break;
    case PROP_HEIGHT:
      g_value_set_int (value, overlay->height);
      break;
    case PROP_WIDTH_RELATIVE:
      g_value_set_float (value, overlay->width_relative);
      break;
    case PROP_HEIGHT_RELATIVE:
      g_value_set_float (value, overlay->height_relative);
      break;

    case PROP_FIT_TO_FRAME:
      g_value_set_boolean (value, (overlay->width_relative == 1.0
              && overlay->height_relative == 1.0));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
static gboolean
gst_rsvg_overlay_data_sink_event (GstPad * pad, GstObject * parent,
    GstEvent * event)
{
  GstRsvgOverlay *overlay = GST_RSVG_OVERLAY (GST_PAD_PARENT (pad));

  GST_LOG_OBJECT (pad, "Got %s event", GST_EVENT_TYPE_NAME (event));

  switch (GST_EVENT_TYPE (event)) {

    case GST_EVENT_EOS:{
      guint data_size;

      GST_RSVG_LOCK (overlay);
      /* FIXME: rsvgdec looks for </svg> in data to determine the end
         of SVG code. Should we really do the same here? IOW, could
         data be sent and _pushed() before the EOS gets processed? */
      data_size = gst_adapter_available (overlay->adapter);
      if (data_size) {
        gst_rsvg_overlay_set_svg_data (overlay,
            (const gchar *) gst_adapter_take (overlay->adapter, data_size),
            FALSE);
        gst_adapter_clear (overlay->adapter);
      }
      GST_RSVG_UNLOCK (overlay);
    }
      break;

    case GST_EVENT_FLUSH_STOP:
      gst_adapter_clear (overlay->adapter);
      break;

    default:
      break;
  }

  /* Dropping all events here */
  gst_event_unref (event);
  return TRUE;
}
Пример #7
0
static GstFlowReturn
gst_rsvg_overlay_transform_ip (GstBaseTransform * btrans, GstBuffer * buf)
{
  GstRsvgOverlay *overlay = GST_RSVG_OVERLAY (btrans);
  cairo_surface_t *surface;
  cairo_t *cr;
  double applied_x_offset = (double) overlay->x_offset;
  double applied_y_offset = (double) overlay->y_offset;
  int applied_width = overlay->width;
  int applied_height = overlay->height;

  GST_RSVG_LOCK (overlay);
  if (!overlay->handle) {
    GST_RSVG_UNLOCK (overlay);
    return GST_FLOW_OK;
  }

  surface =
      cairo_image_surface_create_for_data (GST_BUFFER_DATA (buf),
      CAIRO_FORMAT_ARGB32, overlay->caps_width, overlay->caps_height,
      overlay->caps_width * 4);
  if (G_UNLIKELY (!surface))
    return GST_FLOW_ERROR;

  cr = cairo_create (surface);
  if (G_UNLIKELY (!cr)) {
    cairo_surface_destroy (surface);
    return GST_FLOW_ERROR;
  }

  /* Compute relative dimensions if absolute dimensions are not set */
  if (!applied_x_offset && overlay->x_relative) {
    applied_x_offset = overlay->x_relative * overlay->caps_width;
  }
  if (!applied_y_offset && overlay->y_relative) {
    applied_y_offset = overlay->y_relative * overlay->caps_height;
  }
  if (!applied_width && overlay->width_relative) {
    applied_width = (int) (overlay->width_relative * overlay->caps_width);
  }
  if (!applied_height && overlay->height_relative) {
    applied_height = (int) (overlay->height_relative * overlay->caps_height);
  }

  if (applied_x_offset || applied_y_offset) {
    cairo_translate (cr, applied_x_offset, applied_y_offset);
  }

  /* Scale when necessary, i.e. an absolute or relative dimension has been specified. */
  if ((applied_width || applied_height) && overlay->svg_width
      && overlay->svg_height) {
    /* If may happen that only one of the dimension is specified. Use
       the original SVG size for the other dimension. */
    if (!applied_width)
      applied_width = overlay->svg_width;
    if (!applied_height)
      applied_height = overlay->svg_height;

    cairo_scale (cr, (double) applied_width / overlay->svg_width,
        (double) applied_height / overlay->svg_height);
  }
  rsvg_handle_render_cairo (overlay->handle, cr);
  GST_RSVG_UNLOCK (overlay);

  cairo_destroy (cr);
  cairo_surface_destroy (surface);

  return GST_FLOW_OK;
}
Пример #8
0
static void
gst_rsvg_overlay_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstRsvgOverlay *overlay = GST_RSVG_OVERLAY (object);

  GST_RSVG_LOCK (overlay);

  switch (prop_id) {
    case PROP_DATA:
    {
      gst_rsvg_overlay_set_svg_data (overlay, g_value_get_string (value),
          FALSE);
      break;
    }
    case PROP_FILENAME:
    {
      gst_rsvg_overlay_set_svg_data (overlay, g_value_get_string (value), TRUE);
      break;
    }
    case PROP_FIT_TO_FRAME:
    {
      if (g_value_get_boolean (value)) {
        overlay->x_offset = 0;
        overlay->y_offset = 0;
        overlay->x_relative = 0.0;
        overlay->y_relative = 0.0;
        overlay->width = 0;
        overlay->height = 0;
        overlay->width_relative = 1.0;
        overlay->height_relative = 1.0;
      } else {
        overlay->width_relative = 0;
        overlay->height_relative = 0;
      }
      break;
    }
    case PROP_X:
    {
      overlay->x_offset = g_value_get_int (value);
      break;
    }
    case PROP_Y:
    {
      overlay->y_offset = g_value_get_int (value);
      break;
    }
    case PROP_X_RELATIVE:
    {
      overlay->x_relative = g_value_get_float (value);
      break;
    }
    case PROP_Y_RELATIVE:
    {
      overlay->y_relative = g_value_get_float (value);
      break;
    }

    case PROP_WIDTH:
    {
      overlay->width = g_value_get_int (value);
      break;
    }
    case PROP_HEIGHT:
    {
      overlay->height = g_value_get_int (value);
      break;
    }
    case PROP_WIDTH_RELATIVE:
    {
      overlay->width_relative = g_value_get_float (value);
      break;
    }
    case PROP_HEIGHT_RELATIVE:
    {
      overlay->height_relative = g_value_get_float (value);
      break;
    }

    default:
    {
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
  }

  GST_RSVG_UNLOCK (overlay);
}
static GstFlowReturn
gst_rsvg_overlay_transform_frame_ip (GstVideoFilter * vfilter,
    GstVideoFrame * frame)
{
  GstRsvgOverlay *overlay = GST_RSVG_OVERLAY (vfilter);
  cairo_surface_t *surface;
  cairo_t *cr;
  double applied_x_offset = (double) overlay->x_offset;
  double applied_y_offset = (double) overlay->y_offset;
  int applied_width = overlay->width;
  int applied_height = overlay->height;

  GST_RSVG_LOCK (overlay);
  if (!overlay->handle) {
    GST_RSVG_UNLOCK (overlay);
    return GST_FLOW_OK;
  }

  surface =
      cairo_image_surface_create_for_data (GST_VIDEO_FRAME_PLANE_DATA (frame,
          0), CAIRO_FORMAT_ARGB32, GST_VIDEO_FRAME_WIDTH (frame),
      GST_VIDEO_FRAME_HEIGHT (frame), GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0));
  if (G_UNLIKELY (!surface))
    return GST_FLOW_ERROR;

  cr = cairo_create (surface);
  if (G_UNLIKELY (!cr)) {
    cairo_surface_destroy (surface);
    return GST_FLOW_ERROR;
  }

  /* Compute relative dimensions if absolute dimensions are not set */
  if (!applied_x_offset && overlay->x_relative) {
    applied_x_offset = overlay->x_relative * GST_VIDEO_FRAME_WIDTH (frame);
  }
  if (!applied_y_offset && overlay->y_relative) {
    applied_y_offset = overlay->y_relative * GST_VIDEO_FRAME_HEIGHT (frame);
  }
  if (!applied_width && overlay->width_relative) {
    applied_width =
        (int) (overlay->width_relative * GST_VIDEO_FRAME_WIDTH (frame));
  }
  if (!applied_height && overlay->height_relative) {
    applied_height =
        (int) (overlay->height_relative * GST_VIDEO_FRAME_HEIGHT (frame));
  }

  if (applied_x_offset || applied_y_offset) {
    cairo_translate (cr, applied_x_offset, applied_y_offset);
  }

  /* Scale when necessary, i.e. an absolute or relative dimension has been specified. */
  if ((applied_width || applied_height) && overlay->svg_width
      && overlay->svg_height) {
    /* If may happen that only one of the dimension is specified. Use
       the original SVG size for the other dimension. */
    if (!applied_width)
      applied_width = overlay->svg_width;
    if (!applied_height)
      applied_height = overlay->svg_height;

    cairo_scale (cr, (double) applied_width / overlay->svg_width,
        (double) applied_height / overlay->svg_height);
  }
  rsvg_handle_render_cairo (overlay->handle, cr);
  GST_RSVG_UNLOCK (overlay);

  cairo_destroy (cr);
  cairo_surface_destroy (surface);

  return GST_FLOW_OK;
}