static gboolean
gst_v4l2_video_dec_stop (GstVideoDecoder * decoder)
{
  GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);

  GST_DEBUG_OBJECT (self, "Stopping");

  gst_v4l2_object_unlock (self->v4l2output);
  gst_v4l2_object_unlock (self->v4l2capture);

  /* Wait for capture thread to stop */
  gst_pad_stop_task (decoder->srcpad);

  GST_VIDEO_DECODER_STREAM_LOCK (decoder);
  self->output_flow = GST_FLOW_OK;
  GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);

  /* Should have been flushed already */
  g_assert (g_atomic_int_get (&self->active) == FALSE);
  g_assert (g_atomic_int_get (&self->processing) == FALSE);

  gst_v4l2_object_stop (self->v4l2output);
  gst_v4l2_object_stop (self->v4l2capture);

  if (self->input_state) {
    gst_video_codec_state_unref (self->input_state);
    self->input_state = NULL;
  }

  GST_DEBUG_OBJECT (self, "Stopped");

  return TRUE;
}
static gboolean
gst_v4l2_transform_stop (GstBaseTransform * trans)
{
  GstV4l2Transform *self = GST_V4L2_TRANSFORM (trans);

  GST_DEBUG_OBJECT (self, "Stop");

  gst_v4l2_object_stop (self->v4l2output);
  gst_v4l2_object_stop (self->v4l2capture);
  gst_caps_replace (&self->incaps, NULL);
  gst_caps_replace (&self->outcaps, NULL);

  return TRUE;
}
static gboolean
gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
{
  GstV4l2Src *v4l2src;
  GstV4l2Object *obj;

  v4l2src = GST_V4L2SRC (src);
  obj = v4l2src->v4l2object;

  /* make sure the caps changed before doing anything */
  if (gst_v4l2_object_caps_equal (obj, caps))
    return TRUE;

  /* make sure we stop capturing and dealloc buffers */
  if (!gst_v4l2_object_stop (obj))
    return FALSE;

  g_signal_emit (v4l2src, gst_v4l2_signals[SIGNAL_PRE_SET_FORMAT], 0,
      v4l2src->v4l2object->video_fd, caps);

  if (!gst_v4l2_object_set_format (obj, caps))
    /* error already posted */
    return FALSE;

  return TRUE;
}
Beispiel #4
0
static gboolean
gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
{
  GstV4l2Src *v4l2src;
  GstV4l2Object *obj;

  v4l2src = GST_V4L2SRC (src);
  obj = v4l2src->v4l2object;

  /* make sure the caps changed before doing anything */
  if (gst_v4l2_object_caps_equal (obj, caps))
    return TRUE;

  if (GST_V4L2_IS_ACTIVE (obj)) {
    /* Just check if the format is acceptable, once we know
     * no buffers should be outstanding we try S_FMT.
     *
     * Basesrc will do an allocation query that
     * should indirectly reclaim buffers, after that we can
     * set the format and then configure our pool */
    if (gst_v4l2_object_try_format (obj, caps)) {
      v4l2src->renegotiation_adjust = v4l2src->offset + 1;
      v4l2src->pending_set_fmt = TRUE;
    } else
      return FALSE;
  } else {
    /* make sure we stop capturing and dealloc buffers */
    if (!gst_v4l2_object_stop (obj))
      return FALSE;

    return gst_v4l2src_set_format (v4l2src, caps);
  }

  return TRUE;
}
Beispiel #5
0
static gboolean
gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
{
  GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink);
  GstV4l2Object *obj = v4l2sink->v4l2object;

  LOG_CAPS (v4l2sink, caps);

  if (!GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) {
    GST_DEBUG_OBJECT (v4l2sink, "device is not open");
    return FALSE;
  }

  /* make sure the caps changed before doing anything */
  if (gst_v4l2_object_caps_equal (obj, caps))
    return TRUE;

  if (!gst_v4l2_object_stop (obj))
    goto stop_failed;

  if (!gst_v4l2_object_set_format (v4l2sink->v4l2object, caps))
    goto invalid_format;

  gst_v4l2sink_sync_overlay_fields (v4l2sink);
  gst_v4l2sink_sync_crop_fields (v4l2sink);

#ifdef HAVE_XVIDEO
  gst_v4l2_video_overlay_prepare_window_handle (v4l2sink->v4l2object, TRUE);
#endif

  GST_INFO_OBJECT (v4l2sink, "outputting buffers via mmap()");

  v4l2sink->video_width = GST_V4L2_WIDTH (v4l2sink->v4l2object);
  v4l2sink->video_height = GST_V4L2_HEIGHT (v4l2sink->v4l2object);

  /* TODO: videosink width/height should be scaled according to
   * pixel-aspect-ratio
   */
  GST_VIDEO_SINK_WIDTH (v4l2sink) = v4l2sink->video_width;
  GST_VIDEO_SINK_HEIGHT (v4l2sink) = v4l2sink->video_height;

  return TRUE;

  /* ERRORS */
stop_failed:
  {
    GST_DEBUG_OBJECT (v4l2sink, "failed to stop streaming");
    return FALSE;
  }
invalid_format:
  {
    /* error already posted */
    GST_DEBUG_OBJECT (v4l2sink, "can't set format");
    return FALSE;
  }
}
Beispiel #6
0
static GstStateChangeReturn
gst_v4l2sink_change_state (GstElement * element, GstStateChange transition)
{
  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
  GstV4l2Sink *v4l2sink = GST_V4L2SINK (element);

  GST_DEBUG_OBJECT (v4l2sink, "%d -> %d",
      GST_STATE_TRANSITION_CURRENT (transition),
      GST_STATE_TRANSITION_NEXT (transition));

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      /* open the device */
      if (!gst_v4l2_object_open (v4l2sink->v4l2object))
        return GST_STATE_CHANGE_FAILURE;
      break;
    default:
      break;
  }

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

  switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      if (!gst_v4l2_object_stop (v4l2sink->v4l2object))
        return GST_STATE_CHANGE_FAILURE;
      break;
    case GST_STATE_CHANGE_READY_TO_NULL:
      /* we need to call stop here too */
      if (!gst_v4l2_object_stop (v4l2sink->v4l2object))
        return GST_STATE_CHANGE_FAILURE;
      /* close the device */
      if (!gst_v4l2_object_close (v4l2sink->v4l2object))
        return GST_STATE_CHANGE_FAILURE;
      break;
    default:
      break;
  }

  return ret;
}
static gboolean
gst_v4l2src_stop (GstBaseSrc * src)
{
  GstV4l2Src *v4l2src = GST_V4L2SRC (src);
  GstV4l2Object *obj = v4l2src->v4l2object;

  if (GST_V4L2_IS_ACTIVE (obj)) {
    if (!gst_v4l2_object_stop (obj))
      return FALSE;
  }
  return TRUE;
}
static gboolean
gst_v4l2_transform_set_caps (GstBaseTransform * trans, GstCaps * incaps,
    GstCaps * outcaps)
{
  GstV4l2Transform *self = GST_V4L2_TRANSFORM (trans);

  if (self->incaps && self->outcaps) {
    if (gst_caps_is_equal (incaps, self->incaps) &&
        gst_caps_is_equal (outcaps, self->outcaps)) {
      GST_DEBUG_OBJECT (trans, "Caps did not changed");
      return TRUE;
    }
  }

  /* TODO Add renegotiation support */
  g_return_val_if_fail (!GST_V4L2_IS_ACTIVE (self->v4l2output), FALSE);
  g_return_val_if_fail (!GST_V4L2_IS_ACTIVE (self->v4l2capture), FALSE);

  gst_caps_replace (&self->incaps, incaps);
  gst_caps_replace (&self->outcaps, outcaps);

  if (!gst_v4l2_object_set_format (self->v4l2output, incaps))
    goto incaps_failed;

  if (!gst_v4l2_object_set_format (self->v4l2capture, outcaps))
    goto outcaps_failed;

  /* FIXME implement fallback if crop not supported */
  if (!gst_v4l2_object_set_crop (self->v4l2output))
    goto failed;

  if (!gst_v4l2_object_set_crop (self->v4l2capture))
    goto failed;

  return TRUE;

incaps_failed:
  {
    GST_ERROR_OBJECT (self, "failed to set input caps: %" GST_PTR_FORMAT,
        incaps);
    goto failed;
  }
outcaps_failed:
  {
    gst_v4l2_object_stop (self->v4l2output);
    GST_ERROR_OBJECT (self, "failed to set output caps: %" GST_PTR_FORMAT,
        outcaps);
    goto failed;
  }
failed:
  return FALSE;
}
Beispiel #9
0
static GstStateChangeReturn
gst_v4l2sink_change_state (GstElement * element, GstStateChange transition)
{
    GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
    GstV4l2Sink *v4l2sink = GST_V4L2SINK (element);

    GST_DEBUG_OBJECT (v4l2sink, "%d -> %d",
                      GST_STATE_TRANSITION_CURRENT (transition),
                      GST_STATE_TRANSITION_NEXT (transition));

    switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
        /* open the device */
        if (!gst_v4l2_object_start (v4l2sink->v4l2object))
            return GST_STATE_CHANGE_FAILURE;
        break;
    default:
        break;
    }

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

    switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
        if (v4l2sink->state == STATE_STREAMING) {
            if (!gst_v4l2_object_stop_streaming (v4l2sink->v4l2object)) {
                return GST_STATE_CHANGE_FAILURE;
            }
            v4l2sink->state = STATE_PENDING_STREAMON;
        }
        break;
    case GST_STATE_CHANGE_READY_TO_NULL:
        if (NULL != v4l2sink->pool)
            gst_v4l2_buffer_pool_destroy (v4l2sink->pool);
        v4l2sink->pool = NULL;
        /* close the device */
        if (!gst_v4l2_object_stop (v4l2sink->v4l2object))
            return GST_STATE_CHANGE_FAILURE;
        v4l2sink->state = STATE_OFF;
        break;
    default:
        break;
    }

    return ret;
}
Beispiel #10
0
static gboolean
gst_v4l2src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
{
  GstV4l2Src *src = GST_V4L2SRC (bsrc);
  gboolean ret = TRUE;

  if (src->pending_set_fmt) {
    GstCaps *caps = gst_pad_get_current_caps (GST_BASE_SRC_PAD (bsrc));

    if (!gst_v4l2_object_stop (src->v4l2object))
      return FALSE;
    ret = gst_v4l2src_set_format (src, caps);
    gst_caps_unref (caps);
    src->pending_set_fmt = FALSE;
  }

  if (ret) {
    ret = gst_v4l2_object_decide_allocation (src->v4l2object, query);
    if (ret)
      ret = GST_BASE_SRC_CLASS (parent_class)->decide_allocation (bsrc, query);
  }

  if (ret) {
    if (!gst_buffer_pool_set_active (src->v4l2object->pool, TRUE))
      goto activate_failed;
  }

  return ret;

activate_failed:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS,
        (_("Failed to allocate required memory.")),
        ("Buffer pool activation failed"));
    return FALSE;
  }
}