コード例 #1
0
ファイル: gstksvideosrc.c プロジェクト: dylansong77/gstreamer
static gboolean
gst_ks_video_src_query (GstBaseSrc * basesrc, GstQuery * query)
{
  GstKsVideoSrc *self = GST_KS_VIDEO_SRC (basesrc);
  GstKsVideoSrcPrivate *priv = GST_KS_VIDEO_SRC_GET_PRIVATE (self);
  gboolean result = FALSE;

  switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_LATENCY:{
      GstClockTime min_latency, max_latency;

      if (priv->device == NULL)
        goto beach;

      result = gst_ks_video_device_get_latency (priv->device, &min_latency,
          &max_latency);
      if (!result)
        goto beach;

      GST_DEBUG_OBJECT (self, "reporting latency of min %" GST_TIME_FORMAT
          " max %" GST_TIME_FORMAT,
          GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));

      gst_query_set_latency (query, TRUE, min_latency, max_latency);
      break;
    }
    default:
      result = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
      break;
  }

beach:
  return result;
}
コード例 #2
0
ファイル: gstksvideosrc.c プロジェクト: dylansong77/gstreamer
static GstStateChangeReturn
gst_ks_video_src_change_state (GstElement * element, GstStateChange transition)
{
  GstKsVideoSrc *self = GST_KS_VIDEO_SRC (element);
  GstKsVideoSrcPrivate *priv = GST_KS_VIDEO_SRC_GET_PRIVATE (self);
  GstStateChangeReturn ret;

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      if (priv->enable_quirks)
        gst_ks_video_src_apply_driver_quirks (self);
      if (!gst_ks_video_src_start_worker (self))
        goto open_failed;
      break;
  }

  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);

  switch (transition) {
    case GST_STATE_CHANGE_READY_TO_NULL:
      gst_ks_video_src_stop_worker (self);
      break;
  }

  return ret;

  /* ERRORS */
open_failed:
  {
    gst_ks_video_src_stop_worker (self);
    return GST_STATE_CHANGE_FAILURE;
  }
}
コード例 #3
0
ファイル: gstksvideosrc.c プロジェクト: dylansong77/gstreamer
static void
gst_ks_video_src_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstKsVideoSrc *self = GST_KS_VIDEO_SRC (object);
  GstKsVideoSrcPrivate *priv = GST_KS_VIDEO_SRC_GET_PRIVATE (self);

  switch (prop_id) {
    case PROP_DEVICE_PATH:
      g_value_set_string (value, priv->device_path);
      break;
    case PROP_DEVICE_NAME:
      g_value_set_string (value, priv->device_name);
      break;
    case PROP_DEVICE_INDEX:
      g_value_set_int (value, priv->device_index);
      break;
    case PROP_DO_STATS:
      GST_OBJECT_LOCK (object);
      g_value_set_boolean (value, priv->do_stats);
      GST_OBJECT_UNLOCK (object);
      break;
    case PROP_FPS:
      GST_OBJECT_LOCK (object);
      g_value_set_int (value, priv->fps);
      GST_OBJECT_UNLOCK (object);
      break;
    case PROP_ENABLE_QUIRKS:
      g_value_set_boolean (value, priv->enable_quirks);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
コード例 #4
0
ファイル: gstksvideosrc.c プロジェクト: dylansong77/gstreamer
static gboolean
gst_ks_video_src_unlock_stop (GstBaseSrc * basesrc)
{
  GstKsVideoSrc *self = GST_KS_VIDEO_SRC (basesrc);
  GstKsVideoSrcPrivate *priv = GST_KS_VIDEO_SRC_GET_PRIVATE (self);

  GST_DEBUG_OBJECT (self, "%s", G_STRFUNC);

  gst_ks_video_device_cancel_stop (priv->device);
  return TRUE;
}
コード例 #5
0
ファイル: gstksvideosrc.c プロジェクト: dylansong77/gstreamer
static GstCaps *
gst_ks_video_src_get_caps (GstBaseSrc * basesrc)
{
  GstKsVideoSrc *self = GST_KS_VIDEO_SRC (basesrc);
  GstKsVideoSrcPrivate *priv = GST_KS_VIDEO_SRC_GET_PRIVATE (self);

  if (priv->device != NULL)
    return gst_ks_video_device_get_available_caps (priv->device);
  else
    return NULL;                /* BaseSrc will return template caps */
}
コード例 #6
0
ファイル: gstksvideosrc.c プロジェクト: dylansong77/gstreamer
static void
gst_ks_video_src_finalize (GObject * object)
{
  GstKsVideoSrc *self = GST_KS_VIDEO_SRC (object);
  GstKsVideoSrcPrivate *priv = GST_KS_VIDEO_SRC_GET_PRIVATE (self);

  g_free (priv->device_name);
  g_free (priv->device_path);

  G_OBJECT_CLASS (parent_class)->finalize (object);
}
コード例 #7
0
ファイル: gstksvideosrc.c プロジェクト: dylansong77/gstreamer
static gboolean
gst_ks_video_src_set_clock (GstElement * element, GstClock * clock)
{
  GstKsVideoSrc *self = GST_KS_VIDEO_SRC (element);
  GstKsVideoSrcPrivate *priv = GST_KS_VIDEO_SRC_GET_PRIVATE (self);

  GST_OBJECT_LOCK (element);
  if (clock != NULL && priv->ksclock != NULL)
    gst_ks_clock_provide_master_clock (priv->ksclock, clock);
  GST_OBJECT_UNLOCK (element);

  return TRUE;
}
コード例 #8
0
ファイル: gstksvideosrc.c プロジェクト: dylansong77/gstreamer
static gboolean
gst_ks_video_src_set_caps (GstBaseSrc * basesrc, GstCaps * caps)
{
  GstKsVideoSrc *self = GST_KS_VIDEO_SRC (basesrc);
  GstKsVideoSrcPrivate *priv = GST_KS_VIDEO_SRC_GET_PRIVATE (self);

  if (priv->device == NULL)
    return FALSE;

  KS_WORKER_LOCK (priv);
  priv->worker_pending_caps = caps;
  KS_WORKER_NOTIFY (priv);
  while (priv->worker_pending_caps == caps)
    KS_WORKER_WAIT_FOR_RESULT (priv);
  KS_WORKER_UNLOCK (priv);

  return priv->worker_setcaps_result;
}
コード例 #9
0
ファイル: gstksvideosrc.c プロジェクト: dylansong77/gstreamer
static GValueArray *
gst_ks_video_src_probe_get_values (GstPropertyProbe * probe, guint prop_id,
    const GParamSpec * pspec)
{
  GstKsVideoSrc *src = GST_KS_VIDEO_SRC (probe);
  GValueArray *array = NULL;

  switch (prop_id) {
    case PROP_DEVICE_NAME:
      array = gst_ks_video_src_get_device_name_values (src);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
      break;
  }

  return array;
}
コード例 #10
0
static GstBuffer *
gst_ks_video_src_alloc_buffer (guint size, guint alignment, gpointer user_data)
{
    GstKsVideoSrc *self = GST_KS_VIDEO_SRC (user_data);
    GstBuffer *buf;
    GstAllocationParams params = { 0, alignment - 1, 0, 0, };

    buf = gst_buffer_new_allocate (NULL, size, &params);
    if (buf == NULL)
        goto error_alloc_buffer;

    return buf;

error_alloc_buffer:
    {
        GST_ELEMENT_ERROR (self, CORE, PAD, ("alloc_buffer failed"), (NULL));

        return NULL;
    }
}
コード例 #11
0
ファイル: gstksvideosrc.c プロジェクト: dylansong77/gstreamer
static GstBuffer *
gst_ks_video_src_alloc_buffer (guint size, guint alignment, gpointer user_data)
{
  GstKsVideoSrc *self = GST_KS_VIDEO_SRC (user_data);
  GstBuffer *buf;
  GstCaps *caps;
  GstFlowReturn flow_ret;

  caps = gst_pad_get_negotiated_caps (GST_BASE_SRC_PAD (self));
  if (caps == NULL)
    goto error_no_caps;
  flow_ret = gst_pad_alloc_buffer (GST_BASE_SRC_PAD (self), 0,
      size + (alignment - 1), caps, &buf);
  gst_caps_unref (caps);
  if (G_UNLIKELY (flow_ret != GST_FLOW_OK))
    goto error_alloc_buffer;

  GST_BUFFER_DATA (buf) =
      GSIZE_TO_POINTER ((GPOINTER_TO_SIZE (GST_BUFFER_DATA (buf)) + (alignment -
              1)) & ~(alignment - 1));
  GST_BUFFER_SIZE (buf) = size;

  return buf;

error_no_caps:
  {
    GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
        ("not negotiated"), ("maybe setcaps failed?"));

    return NULL;
  }
error_alloc_buffer:
  {
    GST_ELEMENT_ERROR (self, CORE, PAD, ("alloc_buffer failed"), (NULL));

    return NULL;
  }
}
コード例 #12
0
ファイル: gstksvideosrc.c プロジェクト: dylansong77/gstreamer
static void
gst_ks_video_src_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstKsVideoSrc *self = GST_KS_VIDEO_SRC (object);
  GstKsVideoSrcPrivate *priv = GST_KS_VIDEO_SRC_GET_PRIVATE (self);

  switch (prop_id) {
    case PROP_DEVICE_PATH:
      g_free (priv->device_path);
      priv->device_path = g_value_dup_string (value);
      break;
    case PROP_DEVICE_NAME:
    {
      const gchar *device_name = g_value_get_string (value);
      g_free (priv->device_name);
      priv->device_name = NULL;
      if (device_name && strlen (device_name) != 0)
        priv->device_name = g_strdup (device_name);
    }
      break;
    case PROP_DEVICE_INDEX:
      priv->device_index = g_value_get_int (value);
      break;
    case PROP_DO_STATS:
      GST_OBJECT_LOCK (object);
      priv->do_stats = g_value_get_boolean (value);
      GST_OBJECT_UNLOCK (object);
      break;
    case PROP_ENABLE_QUIRKS:
      priv->enable_quirks = g_value_get_boolean (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
コード例 #13
0
ファイル: gstksvideosrc.c プロジェクト: dylansong77/gstreamer
static GstFlowReturn
gst_ks_video_src_create (GstPushSrc * pushsrc, GstBuffer ** buf)
{
  GstKsVideoSrc *self = GST_KS_VIDEO_SRC (pushsrc);
  GstKsVideoSrcPrivate *priv = GST_KS_VIDEO_SRC_GET_PRIVATE (self);
  GstFlowReturn result;
  GstClockTime presentation_time;
  gulong error_code;
  gchar *error_str;

  g_assert (priv->device != NULL);

  if (!gst_ks_video_device_has_caps (priv->device))
    goto error_no_caps;

  if (G_UNLIKELY (!priv->running)) {
    KS_WORKER_LOCK (priv);
    priv->worker_pending_run = TRUE;
    KS_WORKER_NOTIFY (priv);
    while (priv->worker_pending_run)
      KS_WORKER_WAIT_FOR_RESULT (priv);
    priv->running = priv->worker_run_result;
    error_code = priv->worker_error_code;
    KS_WORKER_UNLOCK (priv);

    if (!priv->running)
      goto error_start_capture;
  }

  do {
    if (*buf != NULL) {
      gst_buffer_unref (*buf);
      *buf = NULL;
    }

    result = gst_ks_video_device_read_frame (priv->device, buf,
        &presentation_time, &error_code, &error_str);
    if (G_UNLIKELY (result != GST_FLOW_OK))
      goto error_read_frame;
  }
  while (!gst_ks_video_src_timestamp_buffer (self, *buf, presentation_time));

  if (G_UNLIKELY (priv->do_stats))
    gst_ks_video_src_update_statistics (self);

  gst_ks_video_device_postprocess_frame (priv->device,
      GST_BUFFER_DATA (*buf), GST_BUFFER_SIZE (*buf));

  return GST_FLOW_OK;

  /* ERRORS */
error_no_caps:
  {
    GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
        ("not negotiated"), ("maybe setcaps failed?"));

    return GST_FLOW_ERROR;
  }
error_start_capture:
  {
    const gchar *debug_str = "failed to change pin state to KSSTATE_RUN";

    switch (error_code) {
      case ERROR_FILE_NOT_FOUND:
        GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
            ("failed to start capture (device unplugged)"), (debug_str));
        break;
      case ERROR_NO_SYSTEM_RESOURCES:
        GST_ELEMENT_ERROR (self, RESOURCE, BUSY,
            ("failed to start capture (device already in use)"), (debug_str));
        break;
      default:
        GST_ELEMENT_ERROR (self, RESOURCE, FAILED,
            ("failed to start capture (0x%08x)", error_code), (debug_str));
        break;
    }

    return GST_FLOW_ERROR;
  }
error_read_frame:
  {
    if (result == GST_FLOW_ERROR) {
      if (error_str != NULL) {
        GST_ELEMENT_ERROR (self, RESOURCE, READ,
            ("read failed: %s [0x%08x]", error_str, error_code),
            ("gst_ks_video_device_read_frame failed"));
      }
    } else if (result == GST_FLOW_UNEXPECTED) {
      GST_ELEMENT_ERROR (self, RESOURCE, READ,
          ("read failed"), ("gst_ks_video_device_read_frame failed"));
    }

    g_free (error_str);

    return result;
  }
}
コード例 #14
0
static GstFlowReturn
gst_ks_video_src_create (GstPushSrc * pushsrc, GstBuffer ** buffer)
{
  GstKsVideoSrc *self = GST_KS_VIDEO_SRC (pushsrc);
  GstKsVideoSrcPrivate *priv = GST_KS_VIDEO_SRC_GET_PRIVATE (self);
  guint buf_size;
  GstCaps *caps;
  GstBuffer *buf = NULL;
  GstFlowReturn result;
  GstClockTime presentation_time;
  gulong error_code;
  gchar *error_str;

  g_assert (priv->device != NULL);

  if (!gst_ks_video_device_has_caps (priv->device))
    goto error_no_caps;

  buf_size = gst_ks_video_device_get_frame_size (priv->device);
  g_assert (buf_size);

  caps = gst_pad_get_negotiated_caps (GST_BASE_SRC_PAD (self));
  if (caps == NULL)
    goto error_no_caps;
  result = gst_pad_alloc_buffer (GST_BASE_SRC_PAD (self), priv->offset,
      buf_size, caps, &buf);
  gst_caps_unref (caps);
  if (G_UNLIKELY (result != GST_FLOW_OK))
    goto error_alloc_buffer;

  if (G_UNLIKELY (!priv->running)) {
    KS_WORKER_LOCK (priv);
    priv->worker_pending_run = TRUE;
    KS_WORKER_NOTIFY (priv);
    while (priv->worker_pending_run)
      KS_WORKER_WAIT_FOR_RESULT (priv);
    priv->running = priv->worker_run_result;
    KS_WORKER_UNLOCK (priv);

    if (!priv->running)
      goto error_start_capture;
  }

  do {
    gulong bytes_read;

    result = gst_ks_video_device_read_frame (priv->device,
        GST_BUFFER_DATA (buf), buf_size, &bytes_read, &presentation_time,
        &error_code, &error_str);
    if (G_UNLIKELY (result != GST_FLOW_OK))
      goto error_read_frame;

    GST_BUFFER_SIZE (buf) = bytes_read;
  }
  while (!gst_ks_video_src_timestamp_buffer (self, buf, presentation_time));

  if (G_UNLIKELY (priv->do_stats))
    gst_ks_video_src_update_statistics (self);

  gst_ks_video_device_postprocess_frame (priv->device,
      GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));

  *buffer = buf;
  return GST_FLOW_OK;

  /* ERRORS */
error_no_caps:
  {
    GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
        ("not negotiated"), ("maybe setcaps failed?"));

    return GST_FLOW_ERROR;
  }
error_start_capture:
  {
    GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ,
        ("could not start capture"),
        ("failed to change pin state to KSSTATE_RUN"));

    return GST_FLOW_ERROR;
  }
error_alloc_buffer:
  {
    GST_ELEMENT_ERROR (self, CORE, PAD, ("alloc_buffer failed"), (NULL));

    return result;
  }
error_read_frame:
  {
    if (result != GST_FLOW_WRONG_STATE && result != GST_FLOW_UNEXPECTED) {
      GST_ELEMENT_ERROR (self, RESOURCE, READ,
          ("read failed: %s [0x%08x]", error_str, error_code),
          ("gst_ks_video_device_read_frame failed"));
    }

    g_free (error_str);
    gst_buffer_unref (buf);

    return result;
  }
}