Ejemplo n.º 1
1
/**
 * gst_app_src_get_caps:
 * @appsrc: a #GstAppSrc
 *
 * Get the configured caps on @appsrc.
 *
 * Returns: the #GstCaps produced by the source. gst_caps_unref() after usage.
 */
GstCaps *
gst_app_src_get_caps (GstAppSrc * appsrc)
{
  g_return_val_if_fail (GST_IS_APP_SRC (appsrc), NULL);

  return gst_app_src_internal_get_caps (GST_BASE_SRC_CAST (appsrc), NULL);
}
Ejemplo n.º 2
0
/**
 * gst_app_src_set_caps:
 * @appsrc: a #GstAppSrc
 * @caps: caps to set
 *
 * Set the capabilities on the appsrc element.  This function takes
 * a copy of the caps structure. After calling this method, the source will
 * only produce caps that match @caps. @caps must be fixed and the caps on the
 * buffers must match the caps or left NULL.
 */
void
gst_app_src_set_caps (GstAppSrc * appsrc, const GstCaps * caps)
{
  GstCaps *old;
  GstAppSrcPrivate *priv;

  g_return_if_fail (GST_IS_APP_SRC (appsrc));

  priv = appsrc->priv;

  g_mutex_lock (&priv->mutex);

  GST_OBJECT_LOCK (appsrc);
  GST_DEBUG_OBJECT (appsrc, "setting caps to %" GST_PTR_FORMAT, caps);
  if ((old = priv->caps) != caps) {
    if (caps)
      priv->caps = gst_caps_copy (caps);
    else
      priv->caps = NULL;
    if (old)
      gst_caps_unref (old);
    priv->new_caps = TRUE;
  }
  GST_OBJECT_UNLOCK (appsrc);

  g_mutex_unlock (&priv->mutex);
}
Ejemplo n.º 3
0
/**
 * gst_app_src_end_of_stream:
 * @appsrc: a #GstAppSrc
 *
 * Indicates to the appsrc element that the last buffer queued in the
 * element is the last buffer of the stream.
 *
 * Returns: #GST_FLOW_OK when the EOS was successfuly queued.
 * #GST_FLOW_FLUSHING when @appsrc is not PAUSED or PLAYING.
 */
GstFlowReturn
gst_app_src_end_of_stream (GstAppSrc * appsrc)
{
  GstAppSrcPrivate *priv;

  g_return_val_if_fail (GST_IS_APP_SRC (appsrc), GST_FLOW_ERROR);

  priv = appsrc->priv;

  g_mutex_lock (&priv->mutex);
  /* can't accept buffers when we are flushing. We can accept them when we are
   * EOS although it will not do anything. */
  if (priv->flushing)
    goto flushing;

  GST_DEBUG_OBJECT (appsrc, "sending EOS");
  priv->is_eos = TRUE;
  g_cond_broadcast (&priv->cond);
  g_mutex_unlock (&priv->mutex);

  return GST_FLOW_OK;

  /* ERRORS */
flushing:
  {
    g_mutex_unlock (&priv->mutex);
    GST_DEBUG_OBJECT (appsrc, "refuse EOS, we are flushing");
    return GST_FLOW_FLUSHING;
  }
}
Ejemplo n.º 4
0
/**
 * gst_app_src_set_callbacks: (skip)
 * @appsrc: a #GstAppSrc
 * @callbacks: the callbacks
 * @user_data: a user_data argument for the callbacks
 * @notify: a destroy notify function
 *
 * Set callbacks which will be executed when data is needed, enough data has
 * been collected or when a seek should be performed.
 * This is an alternative to using the signals, it has lower overhead and is thus
 * less expensive, but also less flexible.
 *
 * If callbacks are installed, no signals will be emitted for performance
 * reasons.
 */
void
gst_app_src_set_callbacks (GstAppSrc * appsrc,
    GstAppSrcCallbacks * callbacks, gpointer user_data, GDestroyNotify notify)
{
  GDestroyNotify old_notify;
  GstAppSrcPrivate *priv;

  g_return_if_fail (GST_IS_APP_SRC (appsrc));
  g_return_if_fail (callbacks != NULL);

  priv = appsrc->priv;

  GST_OBJECT_LOCK (appsrc);
  old_notify = priv->notify;

  if (old_notify) {
    gpointer old_data;

    old_data = priv->user_data;

    priv->user_data = NULL;
    priv->notify = NULL;
    GST_OBJECT_UNLOCK (appsrc);

    old_notify (old_data);

    GST_OBJECT_LOCK (appsrc);
  }
  priv->callbacks = *callbacks;
  priv->user_data = user_data;
  priv->notify = notify;
  GST_OBJECT_UNLOCK (appsrc);
}
Ejemplo n.º 5
0
/**
 * gst_app_src_set_emit_signals:
 * @appsrc: a #GstAppSrc
 * @emit: the new state
 *
 * Make appsrc emit the "new-preroll" and "new-buffer" signals. This option is
 * by default disabled because signal emission is expensive and unneeded when
 * the application prefers to operate in pull mode.
 *
 * Since: 0.10.23
 */
void
gst_app_src_set_emit_signals (GstAppSrc * appsrc, gboolean emit)
{
  g_return_if_fail (GST_IS_APP_SRC (appsrc));

  g_mutex_lock (appsrc->priv->mutex);
  appsrc->priv->emit_signals = emit;
  g_mutex_unlock (appsrc->priv->mutex);
}
Ejemplo n.º 6
0
/**
 * gst_app_src_set_stream_type:
 * @appsrc: a #GstAppSrc
 * @type: the new state
 *
 * Set the stream type on @appsrc. For seekable streams, the "seek" signal must
 * be connected to.
 *
 * A stream_type stream 
 * 
 * Since: 0.10.22
 */
void
gst_app_src_set_stream_type (GstAppSrc * appsrc, GstAppStreamType type)
{
  g_return_if_fail (appsrc != NULL);
  g_return_if_fail (GST_IS_APP_SRC (appsrc));

  GST_OBJECT_LOCK (appsrc);
  GST_DEBUG_OBJECT (appsrc, "setting stream_type of %d", type);
  appsrc->priv->stream_type = type;
  GST_OBJECT_UNLOCK (appsrc);
}
Ejemplo n.º 7
0
/**
 * gst_app_src_set_size:
 * @appsrc: a #GstAppSrc
 * @size: the size to set
 *
 * Set the size of the stream in bytes. A value of -1 means that the size is
 * not known. 
 * 
 * Since: 0.10.22
 */
void
gst_app_src_set_size (GstAppSrc * appsrc, gint64 size)
{
  g_return_if_fail (appsrc != NULL);
  g_return_if_fail (GST_IS_APP_SRC (appsrc));

  GST_OBJECT_LOCK (appsrc);
  GST_DEBUG_OBJECT (appsrc, "setting size of %" G_GINT64_FORMAT, size);
  appsrc->priv->size = size;
  GST_OBJECT_UNLOCK (appsrc);
}
Ejemplo n.º 8
0
/**
 * gst_app_src_get_latency:
 * @appsrc: a #GstAppSrc
 * @min: the min latency
 * @max: the min latency
 *
 * Retrieve the min and max latencies in @min and @max respectively.
 * 
 * Since: 0.10.22
 */
void
gst_app_src_get_latency (GstAppSrc * appsrc, guint64 * min, guint64 * max)
{
  g_return_if_fail (GST_IS_APP_SRC (appsrc));

  g_mutex_lock (appsrc->priv->mutex);
  if (min)
    *min = appsrc->priv->min_latency;
  if (max)
    *max = appsrc->priv->max_latency;
  g_mutex_unlock (appsrc->priv->mutex);
}
Ejemplo n.º 9
0
/**
 * gst_app_src_get_emit_signals:
 * @appsrc: a #GstAppSrc
 *
 * Check if appsrc will emit the "new-preroll" and "new-buffer" signals.
 *
 * Returns: %TRUE if @appsrc is emiting the "new-preroll" and "new-buffer"
 * signals.
 *
 * Since: 0.10.23
 */
gboolean
gst_app_src_get_emit_signals (GstAppSrc * appsrc)
{
  gboolean result;

  g_return_val_if_fail (GST_IS_APP_SRC (appsrc), FALSE);

  g_mutex_lock (appsrc->priv->mutex);
  result = appsrc->priv->emit_signals;
  g_mutex_unlock (appsrc->priv->mutex);

  return result;
}
Ejemplo n.º 10
0
/**
 * gst_app_src_get_max_bytes:
 * @appsrc: a #GstAppSrc
 *
 * Get the maximum amount of bytes that can be queued in @appsrc.
 *
 * Returns: The maximum amount of bytes that can be queued.
 * 
 * Since: 0.10.22
 */
guint64
gst_app_src_get_max_bytes (GstAppSrc * appsrc)
{
  guint64 result;

  g_return_val_if_fail (GST_IS_APP_SRC (appsrc), 0);

  g_mutex_lock (appsrc->priv->mutex);
  result = appsrc->priv->max_bytes;
  GST_DEBUG_OBJECT (appsrc, "getting max-bytes of %" G_GUINT64_FORMAT, result);
  g_mutex_unlock (appsrc->priv->mutex);

  return result;
}
Ejemplo n.º 11
0
/**
 * gst_app_src_set_max_bytes:
 * @appsrc: a #GstAppSrc
 * @max: the maximum number of bytes to queue
 *
 * Set the maximum amount of bytes that can be queued in @appsrc.
 * After the maximum amount of bytes are queued, @appsrc will emit the
 * "enough-data" signal.
 * 
 * Since: 0.10.22
 */
void
gst_app_src_set_max_bytes (GstAppSrc * appsrc, guint64 max)
{
  g_return_if_fail (GST_IS_APP_SRC (appsrc));

  g_mutex_lock (appsrc->priv->mutex);
  if (max != appsrc->priv->max_bytes) {
    GST_DEBUG_OBJECT (appsrc, "setting max-bytes to %" G_GUINT64_FORMAT, max);
    appsrc->priv->max_bytes = max;
    /* signal the change */
    g_cond_broadcast (appsrc->priv->cond);
  }
  g_mutex_unlock (appsrc->priv->mutex);
}
Ejemplo n.º 12
0
/**
 * gst_app_src_get_size:
 * @appsrc: a #GstAppSrc
 *
 * Get the size of the stream in bytes. A value of -1 means that the size is
 * not known. 
 *
 * Returns: the size of the stream previously set with gst_app_src_set_size();
 * 
 * Since: 0.10.22
 */
gint64
gst_app_src_get_size (GstAppSrc * appsrc)
{
  gint64 size;

  g_return_val_if_fail (appsrc != NULL, -1);
  g_return_val_if_fail (GST_IS_APP_SRC (appsrc), -1);

  GST_OBJECT_LOCK (appsrc);
  size = appsrc->priv->size;
  GST_DEBUG_OBJECT (appsrc, "getting size of %" G_GINT64_FORMAT, size);
  GST_OBJECT_UNLOCK (appsrc);

  return size;
}
Ejemplo n.º 13
0
/**
 * gst_app_src_get_stream_type:
 * @appsrc: a #GstAppSrc
 *
 * Get the stream type. Control the stream type of @appsrc
 * with gst_app_src_set_stream_type().
 *
 * Returns: the stream type.
 * 
 * Since: 0.10.22
 */
GstAppStreamType
gst_app_src_get_stream_type (GstAppSrc * appsrc)
{
  gboolean stream_type;

  g_return_val_if_fail (appsrc != NULL, FALSE);
  g_return_val_if_fail (GST_IS_APP_SRC (appsrc), FALSE);

  GST_OBJECT_LOCK (appsrc);
  stream_type = appsrc->priv->stream_type;
  GST_DEBUG_OBJECT (appsrc, "getting stream_type of %d", stream_type);
  GST_OBJECT_UNLOCK (appsrc);

  return stream_type;
}
Ejemplo n.º 14
0
/**
 * gst_app_src_get_caps:
 * @appsrc: a #GstAppSrc
 *
 * Get the configured caps on @appsrc.
 *
 * Returns: the #GstCaps produced by the source. gst_caps_unref() after usage.
 * 
 * Since: 0.10.22
 */
GstCaps *
gst_app_src_get_caps (GstAppSrc * appsrc)
{
  GstCaps *caps;

  g_return_val_if_fail (appsrc != NULL, NULL);
  g_return_val_if_fail (GST_IS_APP_SRC (appsrc), NULL);

  GST_OBJECT_LOCK (appsrc);
  if ((caps = appsrc->priv->caps))
    gst_caps_ref (caps);
  GST_DEBUG_OBJECT (appsrc, "getting caps of %" GST_PTR_FORMAT, caps);
  GST_OBJECT_UNLOCK (appsrc);

  return caps;
}
Ejemplo n.º 15
0
/**
 * gst_app_src_get_current_level_bytes:
 * @appsrc: a #GstAppSrc
 *
 * Get the number of currently queued bytes inside @appsrc.
 *
 * Returns: The number of currently queued bytes.
 *
 * Since: 1.2
 */
guint64
gst_app_src_get_current_level_bytes (GstAppSrc * appsrc)
{
  gint64 queued;
  GstAppSrcPrivate *priv;

  g_return_val_if_fail (GST_IS_APP_SRC (appsrc), -1);

  priv = appsrc->priv;

  GST_OBJECT_LOCK (appsrc);
  queued = priv->queued_bytes;
  GST_DEBUG_OBJECT (appsrc, "current level bytes is %" G_GUINT64_FORMAT,
      queued);
  GST_OBJECT_UNLOCK (appsrc);

  return queued;
}
Ejemplo n.º 16
0
/**
 * gst_app_src_set_caps:
 * @appsrc: a #GstAppSrc
 * @caps: caps to set
 *
 * Set the capabilities on the appsrc element.  This function takes
 * a copy of the caps structure. After calling this method, the source will
 * only produce caps that match @caps. @caps must be fixed and the caps on the
 * buffers must match the caps or left NULL.
 * 
 * Since: 0.10.22
 */
void
gst_app_src_set_caps (GstAppSrc * appsrc, const GstCaps * caps)
{
  GstCaps *old;

  g_return_if_fail (GST_IS_APP_SRC (appsrc));

  GST_OBJECT_LOCK (appsrc);
  GST_DEBUG_OBJECT (appsrc, "setting caps to %" GST_PTR_FORMAT, caps);
  if ((old = appsrc->priv->caps) != caps) {
    if (caps)
      appsrc->priv->caps = gst_caps_copy (caps);
    else
      appsrc->priv->caps = NULL;
    if (old)
      gst_caps_unref (old);
  }
  GST_OBJECT_UNLOCK (appsrc);
}
Ejemplo n.º 17
0
/**
 * gst_app_src_push_buffer:
 * @appsrc: a #GstAppSrc
 * @buffer: a #GstBuffer to push
 *
 * Adds a buffer to the queue of buffers that the appsrc element will
 * push to its source pad.  This function takes ownership of the buffer.
 *
 * Returns: #GST_FLOW_OK when the buffer was successfuly queued.
 * #GST_FLOW_WRONG_STATE when @appsrc is not PAUSED or PLAYING.
 * #GST_FLOW_UNEXPECTED when EOS occured.
 */
GstFlowReturn
gst_app_src_push_buffer (GstAppSrc * appsrc, GstBuffer * buffer)
{
  gboolean first = TRUE;

  g_return_val_if_fail (appsrc, GST_FLOW_ERROR);
  g_return_val_if_fail (GST_IS_APP_SRC (appsrc), GST_FLOW_ERROR);
  g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);

  g_mutex_lock (appsrc->mutex);

  while (TRUE) {
    /* can't accept buffers when we are flushing or EOS */
    if (appsrc->flushing)
      goto flushing;

    if (appsrc->is_eos)
      goto eos;

    if (appsrc->queued_bytes >= appsrc->max_bytes) {
      GST_DEBUG_OBJECT (appsrc, "queue filled (%" G_GUINT64_FORMAT " >= %"
          G_GUINT64_FORMAT ")", appsrc->queued_bytes, appsrc->max_bytes);

      if (first) {
        /* only signal on the first push */
        g_mutex_unlock (appsrc->mutex);

        g_signal_emit (appsrc, gst_app_src_signals[SIGNAL_ENOUGH_DATA], 0,
            NULL);

        g_mutex_lock (appsrc->mutex);
        /* continue to check for flushing/eos after releasing the lock */
        first = FALSE;
        continue;
      }
      if (appsrc->block) {
        GST_DEBUG_OBJECT (appsrc, "waiting for free space");
        /* we are filled, wait until a buffer gets popped or when we
         * flush. */
        g_cond_wait (appsrc->cond, appsrc->mutex);
      } else {
        /* no need to wait for free space, we just pump data into the queue */
        break;
      }
    } else
      break;
  }

  GST_DEBUG_OBJECT (appsrc, "queueing buffer %p", buffer);
  g_queue_push_tail (appsrc->queue, buffer);
  appsrc->queued_bytes += GST_BUFFER_SIZE (buffer);
  g_cond_broadcast (appsrc->cond);
  g_mutex_unlock (appsrc->mutex);

  return GST_FLOW_OK;

  /* ERRORS */
flushing:
  {
    GST_DEBUG_OBJECT (appsrc, "refuse buffer %p, we are flushing", buffer);
    gst_buffer_unref (buffer);
    return GST_FLOW_WRONG_STATE;
  }
eos:
  {
    GST_DEBUG_OBJECT (appsrc, "refuse buffer %p, we are EOS", buffer);
    gst_buffer_unref (buffer);
    return GST_FLOW_UNEXPECTED;
  }
}
Ejemplo n.º 18
0
static GstFlowReturn
gst_app_src_push_buffer_full (GstAppSrc * appsrc, GstBuffer * buffer,
    gboolean steal_ref)
{
  gboolean first = TRUE;
  GstAppSrcPrivate *priv;

  g_return_val_if_fail (GST_IS_APP_SRC (appsrc), GST_FLOW_ERROR);
  g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);

  priv = appsrc->priv;

  g_mutex_lock (&priv->mutex);

  while (TRUE) {
    /* can't accept buffers when we are flushing or EOS */
    if (priv->flushing)
      goto flushing;

    if (priv->is_eos)
      goto eos;

    if (priv->max_bytes && priv->queued_bytes >= priv->max_bytes) {
      GST_DEBUG_OBJECT (appsrc,
          "queue filled (%" G_GUINT64_FORMAT " >= %" G_GUINT64_FORMAT ")",
          priv->queued_bytes, priv->max_bytes);

      if (first) {
        gboolean emit;

        emit = priv->emit_signals;
        /* only signal on the first push */
        g_mutex_unlock (&priv->mutex);

        if (priv->callbacks.enough_data)
          priv->callbacks.enough_data (appsrc, priv->user_data);
        else if (emit)
          g_signal_emit (appsrc, gst_app_src_signals[SIGNAL_ENOUGH_DATA], 0,
              NULL);

        g_mutex_lock (&priv->mutex);
        /* continue to check for flushing/eos after releasing the lock */
        first = FALSE;
        continue;
      }
      if (priv->block) {
        GST_DEBUG_OBJECT (appsrc, "waiting for free space");
        /* we are filled, wait until a buffer gets popped or when we
         * flush. */
        g_cond_wait (&priv->cond, &priv->mutex);
      } else {
        /* no need to wait for free space, we just pump more data into the
         * queue hoping that the caller reacts to the enough-data signal and
         * stops pushing buffers. */
        break;
      }
    } else
      break;
  }

  GST_DEBUG_OBJECT (appsrc, "queueing buffer %p", buffer);
  if (!steal_ref)
    gst_buffer_ref (buffer);
  g_queue_push_tail (priv->queue, buffer);
  priv->queued_bytes += gst_buffer_get_size (buffer);
  g_cond_broadcast (&priv->cond);
  g_mutex_unlock (&priv->mutex);

  return GST_FLOW_OK;

  /* ERRORS */
flushing:
  {
    GST_DEBUG_OBJECT (appsrc, "refuse buffer %p, we are flushing", buffer);
    if (steal_ref)
      gst_buffer_unref (buffer);
    g_mutex_unlock (&priv->mutex);
    return GST_FLOW_FLUSHING;
  }
eos:
  {
    GST_DEBUG_OBJECT (appsrc, "refuse buffer %p, we are EOS", buffer);
    if (steal_ref)
      gst_buffer_unref (buffer);
    g_mutex_unlock (&priv->mutex);
    return GST_FLOW_EOS;
  }
}
Ejemplo n.º 19
0
static gboolean
byzanz_encoder_gstreamer_run (ByzanzEncoder * encoder,
                              GInputStream *  input,
                              GOutputStream * output,
                              gboolean        record_audio,
                              GCancellable *  cancellable,
                              GError **	      error)
{
  ByzanzEncoderGStreamer *gstreamer = BYZANZ_ENCODER_GSTREAMER (encoder);
  ByzanzEncoderGStreamerClass *klass = BYZANZ_ENCODER_GSTREAMER_GET_CLASS (encoder);
  GstElement *sink;
  guint width, height;
  GstMessage *message;
  GstBus *bus;

  if (!byzanz_deserialize_header (input, &width, &height, cancellable, error))
    return FALSE;

  gstreamer->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);

  g_assert (klass->pipeline_string);
  if (record_audio) {
    if (klass->audio_pipeline_string == NULL) {
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
          _("This format does not support recording audio."));
      return FALSE;
    }
    gstreamer->pipeline = gst_parse_launch (klass->audio_pipeline_string, error);
    gstreamer->audiosrc = gst_bin_get_by_name (GST_BIN (gstreamer->pipeline), "audiosrc");
    g_assert (gstreamer->audiosrc);
  } else {
    gstreamer->pipeline = gst_parse_launch (klass->pipeline_string, error);
  }
  if (gstreamer->pipeline == NULL)
    return FALSE;

  g_assert (GST_IS_PIPELINE (gstreamer->pipeline));
  gstreamer->src = GST_APP_SRC (gst_bin_get_by_name (GST_BIN (gstreamer->pipeline), "src"));
  g_assert (GST_IS_APP_SRC (gstreamer->src));
  sink = gst_bin_get_by_name (GST_BIN (gstreamer->pipeline), "sink");
  g_assert (sink);
  g_object_set (sink, "stream", output, NULL);
  g_object_unref (sink);

  gstreamer->caps = gst_caps_new_simple ("video/x-raw",
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
                                         "format", G_TYPE_STRING, "BGRx",
#elif G_BYTE_ORDER == G_BIG_ENDIAN
                                         "format", G_TYPE_STRING, "xRGB",
#else
#error "Please add the Cairo caps format here"
#endif
                                         "width", G_TYPE_INT, width,
                                         "height", G_TYPE_INT, height,
                                         "framerate", GST_TYPE_FRACTION, 0, 1, NULL);
  g_assert (gst_caps_is_fixed (gstreamer->caps));

  gst_app_src_set_caps (gstreamer->src, gstreamer->caps);
  gst_app_src_set_callbacks (gstreamer->src, &callbacks, gstreamer, NULL);
  gst_app_src_set_stream_type (gstreamer->src, GST_APP_STREAM_TYPE_STREAM);
  gst_app_src_set_max_bytes (gstreamer->src, 0);
  g_object_set (gstreamer->src,
                "format", GST_FORMAT_TIME,
                NULL);

  if (!gst_element_set_state (gstreamer->pipeline, GST_STATE_PLAYING)) {
    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Failed to start GStreamer pipeline"));
    return FALSE;
  }

  bus = gst_pipeline_get_bus (GST_PIPELINE (gstreamer->pipeline));
  message = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
  g_object_unref (bus);

  gst_element_set_state (gstreamer->pipeline, GST_STATE_NULL);

  if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR) {
    gst_message_parse_error (message, error, NULL);
    gst_message_unref (message);
    return FALSE;
  }
  gst_message_unref (message);

  return TRUE;
}