예제 #1
0
static void
gst_video_flip_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstVideoFlip *videoflip;
  GstVideoFilter *videofilter;

  g_return_if_fail (GST_IS_VIDEO_FLIP (object));
  videoflip = GST_VIDEO_FLIP (object);
  videofilter = GST_VIDEO_FILTER (object);

  switch (prop_id) {
    case ARG_METHOD:
    {
      GstVideoFlipMethod method;

      method = g_value_get_enum (value);
      if (method != videoflip->method) {
        GstBaseTransform *btrans = GST_BASE_TRANSFORM (videoflip);

        g_mutex_lock (btrans->transform_lock);
        gst_pad_set_caps (btrans->sinkpad, NULL);
        gst_pad_set_caps (btrans->srcpad, NULL);
        g_mutex_unlock (btrans->transform_lock);
        videoflip->method = method;
      }
    }
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
예제 #2
0
static GstFlowReturn
gst_video_flip_transform (GstBaseTransform * trans, GstBuffer * in,
    GstBuffer * out)
{
  GstVideoFlip *videoflip = GST_VIDEO_FLIP (trans);
  guint8 *dest;
  const guint8 *src;

  if (G_UNLIKELY (videoflip->process == NULL))
    goto not_negotiated;

  src = GST_BUFFER_DATA (in);
  dest = GST_BUFFER_DATA (out);

  GST_LOG_OBJECT (videoflip, "videoflip: flipping %dx%d to %dx%d (%s)",
      videoflip->from_width, videoflip->from_height, videoflip->to_width,
      videoflip->to_height, video_flip_methods[videoflip->method].value_nick);

  GST_OBJECT_LOCK (videoflip);
  videoflip->process (videoflip, dest, src);
  GST_OBJECT_UNLOCK (videoflip);

  return GST_FLOW_OK;

not_negotiated:
  GST_ERROR_OBJECT (videoflip, "Not negotiated yet");
  return GST_FLOW_NOT_NEGOTIATED;
}
예제 #3
0
static GstFlowReturn
gst_video_flip_transform (GstBaseTransform * trans, GstBuffer * in,
    GstBuffer * out)
{
  GstVideoFlip *videoflip;
  gpointer dest, src;
  int sw, sh, dw, dh;
  GstFlowReturn ret = GST_FLOW_OK;

  videoflip = GST_VIDEO_FLIP (trans);

  gst_buffer_copy_metadata (out, in, GST_BUFFER_COPY_TIMESTAMPS);

  src = GST_BUFFER_DATA (in);
  dest = GST_BUFFER_DATA (out);
  sw = videoflip->from_width;
  sh = videoflip->from_height;
  dw = videoflip->to_width;
  dh = videoflip->to_height;

  GST_LOG_OBJECT (videoflip, "videoflip: scaling planar 4:1:1 %dx%d to %dx%d",
      sw, sh, dw, dh);

  ret = gst_video_flip_flip (videoflip, dest, src, sw, sh, dw, dh);

  return ret;
}
예제 #4
0
static gboolean
gst_video_flip_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
    GstCaps * outcaps)
{
  GstVideoFlip *vf;
  GstStructure *in_s, *out_s;
  gboolean ret = FALSE;

  vf = GST_VIDEO_FLIP (btrans);

  in_s = gst_caps_get_structure (incaps, 0);
  out_s = gst_caps_get_structure (outcaps, 0);

  if (gst_structure_get_int (in_s, "width", &vf->from_width) &&
      gst_structure_get_int (in_s, "height", &vf->from_height) &&
      gst_structure_get_int (out_s, "width", &vf->to_width) &&
      gst_structure_get_int (out_s, "height", &vf->to_height)) {
    /* Check that they are correct */
    switch (vf->method) {
      case GST_VIDEO_FLIP_METHOD_90R:
      case GST_VIDEO_FLIP_METHOD_90L:
      case GST_VIDEO_FLIP_METHOD_TRANS:
      case GST_VIDEO_FLIP_METHOD_OTHER:
        if ((vf->from_width != vf->to_height) ||
            (vf->from_height != vf->to_width)) {
          GST_DEBUG_OBJECT (vf, "we are inverting width and height but caps "
              "are not correct : %dx%d to %dx%d", vf->from_width,
              vf->from_height, vf->to_width, vf->to_height);
          goto beach;
        }
        break;
      case GST_VIDEO_FLIP_METHOD_IDENTITY:

        break;
      case GST_VIDEO_FLIP_METHOD_180:
      case GST_VIDEO_FLIP_METHOD_HORIZ:
      case GST_VIDEO_FLIP_METHOD_VERT:
        if ((vf->from_width != vf->to_width) ||
            (vf->from_height != vf->to_height)) {
          GST_DEBUG_OBJECT (vf, "we are keeping width and height but caps "
              "are not correct : %dx%d to %dx%d", vf->from_width,
              vf->from_height, vf->to_width, vf->to_height);
          goto beach;
        }
        break;
      default:
        g_assert_not_reached ();
        break;
    }
  }

  ret = TRUE;

beach:
  return ret;
}
예제 #5
0
static GstCaps *
gst_video_flip_transform_caps (GstBaseTransform * trans,
    GstPadDirection direction, GstCaps * caps)
{
  GstVideoFlip *videoflip = GST_VIDEO_FLIP (trans);
  GstCaps *ret;
  gint width, height, i;

  ret = gst_caps_copy (caps);

  for (i = 0; i < gst_caps_get_size (ret); i++) {
    GstStructure *structure = gst_caps_get_structure (ret, i);
    gint par_n, par_d;

    if (gst_structure_get_int (structure, "width", &width) &&
        gst_structure_get_int (structure, "height", &height)) {

      switch (videoflip->method) {
        case GST_VIDEO_FLIP_METHOD_90R:
        case GST_VIDEO_FLIP_METHOD_90L:
        case GST_VIDEO_FLIP_METHOD_TRANS:
        case GST_VIDEO_FLIP_METHOD_OTHER:
          gst_structure_set (structure, "width", G_TYPE_INT, height,
              "height", G_TYPE_INT, width, NULL);
          if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
                  &par_n, &par_d)) {
            if (par_n != 1 || par_d != 1) {
              GValue val = { 0, };

              g_value_init (&val, GST_TYPE_FRACTION);
              gst_value_set_fraction (&val, par_d, par_n);
              gst_structure_set_value (structure, "pixel-aspect-ratio", &val);
              g_value_unset (&val);
            }
          }
          break;
        case GST_VIDEO_FLIP_METHOD_IDENTITY:
        case GST_VIDEO_FLIP_METHOD_180:
        case GST_VIDEO_FLIP_METHOD_HORIZ:
        case GST_VIDEO_FLIP_METHOD_VERT:
          gst_structure_set (structure, "width", G_TYPE_INT, width,
              "height", G_TYPE_INT, height, NULL);
          break;
        default:
          g_assert_not_reached ();
          break;
      }
    }
  }

  GST_DEBUG_OBJECT (videoflip, "transformed %" GST_PTR_FORMAT " to %"
      GST_PTR_FORMAT, caps, ret);

  return ret;
}
예제 #6
0
static void
gst_video_flip_init (GTypeInstance * instance, gpointer g_class)
{
  GstVideoFlip *videoflip = GST_VIDEO_FLIP (instance);
  GstBaseTransform *btrans = GST_BASE_TRANSFORM (instance);

  GST_DEBUG_OBJECT (videoflip, "gst_video_flip_init");

  videoflip->method = GST_VIDEO_FLIP_METHOD_90R;

  gst_pad_set_event_function (btrans->srcpad,
      GST_DEBUG_FUNCPTR (gst_video_flip_handle_src_event));
}
예제 #7
0
static void
gst_video_flip_get_property (GObject * object, guint prop_id, GValue * value,
    GParamSpec * pspec)
{
  GstVideoFlip *videoflip = GST_VIDEO_FLIP (object);

  switch (prop_id) {
    case PROP_METHOD:
      g_value_set_enum (value, videoflip->method);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
예제 #8
0
static void
gst_video_flip_before_transform (GstBaseTransform * trans, GstBuffer * in)
{
  GstVideoFlip *videoflip = GST_VIDEO_FLIP (trans);
  GstClockTime timestamp, stream_time;

  timestamp = GST_BUFFER_TIMESTAMP (in);
  stream_time =
      gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME, timestamp);

  GST_DEBUG_OBJECT (videoflip, "sync to %" GST_TIME_FORMAT,
      GST_TIME_ARGS (timestamp));

  if (GST_CLOCK_TIME_IS_VALID (stream_time))
    gst_object_sync_values (G_OBJECT (videoflip), stream_time);
}
예제 #9
0
static GstCaps *
gst_video_flip_transform_caps (GstBaseTransform * trans,
    GstPadDirection direction, GstCaps * caps)
{
  GstVideoFlip *videoflip;
  GstCaps *ret;
  gint width, height, i;

  videoflip = GST_VIDEO_FLIP (trans);

  ret = gst_caps_copy (caps);

  for (i = 0; i < gst_caps_get_size (ret); i++) {
    GstStructure *structure = gst_caps_get_structure (ret, i);

    if (gst_structure_get_int (structure, "width", &width) &&
        gst_structure_get_int (structure, "height", &height)) {

      switch (videoflip->method) {
        case GST_VIDEO_FLIP_METHOD_90R:
        case GST_VIDEO_FLIP_METHOD_90L:
        case GST_VIDEO_FLIP_METHOD_TRANS:
        case GST_VIDEO_FLIP_METHOD_OTHER:
          gst_structure_set (structure, "width", G_TYPE_INT, height,
              "height", G_TYPE_INT, width, NULL);
          break;
        case GST_VIDEO_FLIP_METHOD_IDENTITY:
        case GST_VIDEO_FLIP_METHOD_180:
        case GST_VIDEO_FLIP_METHOD_HORIZ:
        case GST_VIDEO_FLIP_METHOD_VERT:
          gst_structure_set (structure, "width", G_TYPE_INT, width,
              "height", G_TYPE_INT, height, NULL);
          break;
        default:
          g_assert_not_reached ();
          break;
      }
    }
  }

  GST_DEBUG_OBJECT (videoflip, "transformed %" GST_PTR_FORMAT " to %"
      GST_PTR_FORMAT, caps, ret);

  return ret;
}
예제 #10
0
static gboolean
gst_video_flip_get_unit_size (GstBaseTransform * btrans, GstCaps * caps,
    guint * size)
{
  GstVideoFlip *videoflip = GST_VIDEO_FLIP (btrans);
  GstVideoFormat format;
  gint width, height;

  if (!gst_video_format_parse_caps (caps, &format, &width, &height))
    return FALSE;

  *size = gst_video_format_get_size (format, width, height);

  GST_DEBUG_OBJECT (videoflip, "our frame size is %d bytes (%dx%d)", *size,
      width, height);

  return TRUE;
}
예제 #11
0
static gboolean
gst_video_flip_get_unit_size (GstBaseTransform * btrans, GstCaps * caps,
    guint * size)
{
  GstVideoFlip *videoflip;
  GstStructure *structure;
  gboolean ret = FALSE;
  gint width, height;

  videoflip = GST_VIDEO_FLIP (btrans);

  structure = gst_caps_get_structure (caps, 0);

  if (gst_structure_get_int (structure, "width", &width) &&
      gst_structure_get_int (structure, "height", &height)) {
    *size = GST_VIDEO_I420_SIZE (width, height);
    ret = TRUE;
    GST_DEBUG_OBJECT (videoflip, "our frame size is %d bytes (%dx%d)", *size,
        width, height);
  }

  return ret;
}
예제 #12
0
static void
gst_video_flip_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstVideoFlip *videoflip = GST_VIDEO_FLIP (object);

  switch (prop_id) {
    case PROP_METHOD:
    {
      GstVideoFlipMethod method;

      method = g_value_get_enum (value);
      GST_OBJECT_LOCK (videoflip);
      if (method != videoflip->method) {
        GstBaseTransform *btrans = GST_BASE_TRANSFORM (videoflip);

        GST_DEBUG_OBJECT (videoflip, "Changing method from %s to %s",
            video_flip_methods[videoflip->method].value_nick,
            video_flip_methods[method].value_nick);

        videoflip->method = method;
        GST_OBJECT_UNLOCK (videoflip);

        gst_base_transform_set_passthrough (btrans,
            method == GST_VIDEO_FLIP_METHOD_IDENTITY);
        gst_base_transform_reconfigure (btrans);
      } else {
        GST_OBJECT_UNLOCK (videoflip);
      }
    }
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
예제 #13
0
static gboolean
gst_video_flip_src_event (GstBaseTransform * trans, GstEvent * event)
{
  GstVideoFlip *vf = GST_VIDEO_FLIP (trans);
  gdouble new_x, new_y, x, y;
  GstStructure *structure;

  GST_DEBUG_OBJECT (vf, "handling %s event", GST_EVENT_TYPE_NAME (event));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_NAVIGATION:
      event =
          GST_EVENT (gst_mini_object_make_writable (GST_MINI_OBJECT (event)));

      structure = (GstStructure *) gst_event_get_structure (event);
      if (gst_structure_get_double (structure, "pointer_x", &x) &&
          gst_structure_get_double (structure, "pointer_y", &y)) {
        GST_DEBUG_OBJECT (vf, "converting %fx%f", x, y);
        switch (vf->method) {
          case GST_VIDEO_FLIP_METHOD_90R:
            new_x = y;
            new_y = vf->to_width - x;
            break;
          case GST_VIDEO_FLIP_METHOD_90L:
            new_x = vf->to_height - y;
            new_y = x;
            break;
          case GST_VIDEO_FLIP_METHOD_OTHER:
            new_x = vf->to_height - y;
            new_y = vf->to_width - x;
            break;
          case GST_VIDEO_FLIP_METHOD_TRANS:
            new_x = y;
            new_y = x;
            break;
          case GST_VIDEO_FLIP_METHOD_180:
            new_x = vf->to_width - x;
            new_y = vf->to_height - y;
            break;
          case GST_VIDEO_FLIP_METHOD_HORIZ:
            new_x = vf->to_width - x;
            new_y = y;
            break;
          case GST_VIDEO_FLIP_METHOD_VERT:
            new_x = x;
            new_y = vf->to_height - y;
            break;
          default:
            new_x = x;
            new_y = y;
            break;
        }
        GST_DEBUG_OBJECT (vf, "to %fx%f", new_x, new_y);
        gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, new_x,
            "pointer_y", G_TYPE_DOUBLE, new_y, NULL);
      }
      break;
    default:
      break;
  }

  return TRUE;
}
예제 #14
0
static gboolean
gst_video_flip_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
    GstCaps * outcaps)
{
  GstVideoFlip *vf = GST_VIDEO_FLIP (btrans);
  GstVideoFormat in_format, out_format;
  gboolean ret = FALSE;

  vf->process = NULL;

  if (!gst_video_format_parse_caps (incaps, &in_format, &vf->from_width,
          &vf->from_height)
      || !gst_video_format_parse_caps (outcaps, &out_format, &vf->to_width,
          &vf->to_height))
    goto invalid_caps;

  if (in_format != out_format)
    goto invalid_caps;
  vf->format = in_format;

  /* Check that they are correct */
  switch (vf->method) {
    case GST_VIDEO_FLIP_METHOD_90R:
    case GST_VIDEO_FLIP_METHOD_90L:
    case GST_VIDEO_FLIP_METHOD_TRANS:
    case GST_VIDEO_FLIP_METHOD_OTHER:
      if ((vf->from_width != vf->to_height) ||
          (vf->from_height != vf->to_width)) {
        GST_ERROR_OBJECT (vf, "we are inverting width and height but caps "
            "are not correct : %dx%d to %dx%d", vf->from_width,
            vf->from_height, vf->to_width, vf->to_height);
        goto beach;
      }
      break;
    case GST_VIDEO_FLIP_METHOD_IDENTITY:

      break;
    case GST_VIDEO_FLIP_METHOD_180:
    case GST_VIDEO_FLIP_METHOD_HORIZ:
    case GST_VIDEO_FLIP_METHOD_VERT:
      if ((vf->from_width != vf->to_width) ||
          (vf->from_height != vf->to_height)) {
        GST_ERROR_OBJECT (vf, "we are keeping width and height but caps "
            "are not correct : %dx%d to %dx%d", vf->from_width,
            vf->from_height, vf->to_width, vf->to_height);
        goto beach;
      }
      break;
    default:
      g_assert_not_reached ();
      break;
  }

  ret = TRUE;

  switch (vf->format) {
    case GST_VIDEO_FORMAT_I420:
    case GST_VIDEO_FORMAT_YV12:
    case GST_VIDEO_FORMAT_Y444:
      vf->process = gst_video_flip_planar_yuv;
      break;
    case GST_VIDEO_FORMAT_AYUV:
    case GST_VIDEO_FORMAT_ARGB:
    case GST_VIDEO_FORMAT_ABGR:
    case GST_VIDEO_FORMAT_RGBA:
    case GST_VIDEO_FORMAT_BGRA:
    case GST_VIDEO_FORMAT_xRGB:
    case GST_VIDEO_FORMAT_xBGR:
    case GST_VIDEO_FORMAT_RGBx:
    case GST_VIDEO_FORMAT_BGRx:
    case GST_VIDEO_FORMAT_RGB:
    case GST_VIDEO_FORMAT_BGR:
      vf->process = gst_video_flip_packed_simple;
      break;
    default:
      break;
  }

beach:
  return ret && (vf->process != NULL);

invalid_caps:
  GST_ERROR_OBJECT (vf, "Invalid caps: %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT,
      incaps, outcaps);
  return FALSE;
}