Exemplo n.º 1
0
static void
gst_v4l_xoverlay_set_window_handle (GstXOverlay * overlay, guintptr id)
{
  XID xwindow_id = id;
  GstV4lElement *v4lelement = GST_V4LELEMENT (overlay);
  GstV4lXv *v4lxv;
  XWindowAttributes attr;
  gboolean change = (v4lelement->xwindow_id != xwindow_id);

  GST_LOG_OBJECT (v4lelement, "Changing port to %lx", xwindow_id);

  if (!v4lelement->xv && GST_V4L_IS_OPEN (v4lelement))
    gst_v4l_xoverlay_open (v4lelement);

  v4lxv = v4lelement->xv;

  if (v4lxv)
    g_mutex_lock (v4lxv->mutex);

  if (change) {
    if (v4lelement->xwindow_id && v4lxv) {
      GST_DEBUG_OBJECT (v4lelement,
          "Disabling port %lx", v4lelement->xwindow_id);

      XvSelectPortNotify (v4lxv->dpy, v4lxv->port, 0);
      XvSelectVideoNotify (v4lxv->dpy, v4lelement->xwindow_id, 0);
      XvStopVideo (v4lxv->dpy, v4lxv->port, v4lelement->xwindow_id);
    }

    v4lelement->xwindow_id = xwindow_id;
  }

  if (!v4lxv || xwindow_id == 0) {
    if (v4lxv)
      g_mutex_unlock (v4lxv->mutex);
    return;
  }

  if (change) {
    GST_DEBUG_OBJECT (v4lelement, "Enabling port %lx", xwindow_id);

    /* draw */
    XvSelectPortNotify (v4lxv->dpy, v4lxv->port, 1);
    XvSelectVideoNotify (v4lxv->dpy, v4lelement->xwindow_id, 1);
  }

  XGetWindowAttributes (v4lxv->dpy, v4lelement->xwindow_id, &attr);
  XvPutVideo (v4lxv->dpy, v4lxv->port, v4lelement->xwindow_id,
      DefaultGC (v4lxv->dpy, DefaultScreen (v4lxv->dpy)),
      0, 0, attr.width, attr.height, 0, 0, attr.width, attr.height);

  if (v4lxv->idle_id)
    g_source_remove (v4lxv->idle_id);
  v4lxv->idle_id = g_idle_add (idle_refresh, v4lelement);
  g_mutex_unlock (v4lxv->mutex);
}
Exemplo n.º 2
0
static void
gst_v4l_tuner_set_norm (GstTuner * tuner, GstTunerNorm * norm)
{
  GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
  GstV4lTunerNorm *v4lnorm = GST_V4L_TUNER_NORM (norm);
  gint channel;

  /* assert that we're opened and that we're using a known item */
  g_return_if_fail (GST_V4L_IS_OPEN (v4lelement));
  g_return_if_fail (gst_v4l_tuner_contains_norm (v4lelement, v4lnorm));

  gst_v4l_get_chan_norm (v4lelement, &channel, NULL);
  gst_v4l_set_chan_norm (v4lelement, channel, v4lnorm->index);
}
Exemplo n.º 3
0
static void
gst_v4l_tuner_set_channel (GstTuner * tuner, GstTunerChannel * channel)
{
  GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
  GstV4lTunerChannel *v4lchannel = GST_V4L_TUNER_CHANNEL (channel);
  gint norm;

  /* assert that we're opened and that we're using a known item */
  g_return_if_fail (GST_V4L_IS_OPEN (v4lelement));
  g_return_if_fail (gst_v4l_tuner_contains_channel (v4lelement, v4lchannel));

  gst_v4l_get_chan_norm (v4lelement, NULL, &norm);
  gst_v4l_set_chan_norm (v4lelement, v4lchannel->index, norm);
}
Exemplo n.º 4
0
/* this function is a bit of a last resort */
static void
gst_v4lsrc_fixate (GstBaseSrc * bsrc, GstCaps * caps)
{
    GstStructure *structure;
    int i;
    int targetwidth, targetheight;
    GstV4lSrc *v4lsrc = GST_V4LSRC (bsrc);
    struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap;
    struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;

    if (GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
        GST_DEBUG_OBJECT (v4lsrc, "device reported w: %d-%d, h: %d-%d",
                          vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight);
        targetwidth = vcap->minwidth;
        targetheight = vcap->minheight;
        /* if we can get the current vwin settings, we use those to fixate */
        if (!gst_v4l_get_capabilities (GST_V4LELEMENT (v4lsrc)))
            GST_DEBUG_OBJECT (v4lsrc, "failed getting capabilities");
        else {
            targetwidth = vwin->width;
            targetheight = vwin->height;
        }
    } else {
        GST_DEBUG_OBJECT (v4lsrc, "device closed, guessing");
        targetwidth = 320;
        targetheight = 200;
    }

    GST_DEBUG_OBJECT (v4lsrc, "targetting %dx%d", targetwidth, targetheight);

    for (i = 0; i < gst_caps_get_size (caps); ++i) {
        const GValue *v;

        structure = gst_caps_get_structure (caps, i);
        gst_structure_fixate_field_nearest_int (structure, "width", targetwidth);
        gst_structure_fixate_field_nearest_int (structure, "height", targetheight);
        gst_structure_fixate_field_nearest_fraction (structure, "framerate", 15, 2);

        v = gst_structure_get_value (structure, "format");
        if (v && G_VALUE_TYPE (v) != GST_TYPE_FOURCC) {
            guint32 fourcc;

            g_return_if_fail (G_VALUE_TYPE (v) == GST_TYPE_LIST);

            fourcc = gst_value_get_fourcc (gst_value_list_get_value (v, 0));
            gst_structure_set (structure, "format", GST_TYPE_FOURCC, fourcc, NULL);
        }
    }
}
Exemplo n.º 5
0
static gboolean
gst_v4lsrc_query (GstBaseSrc * bsrc, GstQuery * query)
{
    GstV4lSrc *v4lsrc;
    gboolean res = FALSE;

    v4lsrc = GST_V4LSRC (bsrc);

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

        /* device must be open */
        if (!GST_V4L_IS_OPEN (v4lsrc))
            goto done;

        /* we must have a framerate */
        if (!(res = gst_v4lsrc_get_fps (v4lsrc, &fps_n, &fps_d)))
            goto done;

        /* min latency is the time to capture one frame */
        min_latency = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);

        /* max latency is total duration of the frame buffer */
        max_latency = v4lsrc->mbuf.frames * min_latency;

        GST_DEBUG_OBJECT (bsrc,
                          "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
                          GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));

        /* we are always live, the min latency is 1 frame and the max latency is
         * the complete buffer of frames. */
        gst_query_set_latency (query, TRUE, min_latency, max_latency);

        res = TRUE;
        break;
    }
    default:
        res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
        break;
    }
done:
    return res;
}
Exemplo n.º 6
0
static GstCaps *
gst_v4ljpegsrc_getcaps (GstPad * pad)
{
  GstCaps *list;
  GstV4lJpegSrc *v4ljpegsrc = GST_V4LJPEGSRC (gst_pad_get_parent (pad));
  GstV4lSrc *v4lsrc = GST_V4LSRC (v4ljpegsrc);
  struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap;
  gfloat fps = 0.0;

  if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
    return gst_caps_new_any ();
  }
  if (!v4lsrc->autoprobe) {
    /* FIXME: query current caps and return those, with _any appended */
    return gst_caps_new_any ();
  }

  list = gst_caps_new_simple ("image/jpeg", NULL);
  GST_DEBUG_OBJECT (v4ljpegsrc,
      "Device reports w: %d-%d, h: %d-%d, fps: %f",
      vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight, fps);

  if (vcap->minwidth < vcap->maxwidth) {
    gst_caps_set_simple (list, "width", GST_TYPE_INT_RANGE, vcap->minwidth,
        vcap->maxwidth, NULL);
  } else {
    gst_caps_set_simple (list, "width", G_TYPE_INT, vcap->minwidth, NULL);
  }
  if (vcap->minheight < vcap->maxheight) {
    gst_caps_set_simple (list, "height", GST_TYPE_INT_RANGE, vcap->minheight,
        vcap->maxheight, NULL);
  } else {
    gst_caps_set_simple (list, "height", G_TYPE_INT, vcap->minheight, NULL);
  }

  if (v4lsrc->fps_list) {
    GstStructure *structure = gst_caps_get_structure (list, 0);

    gst_structure_set_value (structure, "framerate", v4lsrc->fps_list);
  }
  GST_DEBUG_OBJECT (v4ljpegsrc, "caps: %" GST_PTR_FORMAT, list);

  return list;
}
Exemplo n.º 7
0
static void
gst_v4l_tuner_set_frequency (GstTuner * tuner,
    GstTunerChannel * channel, gulong frequency)
{
  GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
  GstV4lTunerChannel *v4lchannel = GST_V4L_TUNER_CHANNEL (channel);
  gint chan;

  /* assert that we're opened and that we're using a known item */
  g_return_if_fail (GST_V4L_IS_OPEN (v4lelement));
  g_return_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
          GST_TUNER_CHANNEL_FREQUENCY));
  g_return_if_fail (gst_v4l_tuner_contains_channel (v4lelement, v4lchannel));

  gst_v4l_get_chan_norm (v4lelement, &chan, NULL);
  if (chan == GST_V4L_TUNER_CHANNEL (channel)->index) {
    gst_v4l_set_frequency (v4lelement, v4lchannel->tuner, frequency);
  }
}
Exemplo n.º 8
0
static GstTunerNorm *
gst_v4l_tuner_get_norm (GstTuner * tuner)
{
  GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
  GList *item;
  gint norm;

  /* assert that we're opened */
  g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), NULL);

  gst_v4l_get_chan_norm (v4lelement, NULL, &norm);

  for (item = v4lelement->norms; item != NULL; item = item->next) {
    if (norm == GST_V4L_TUNER_NORM (item->data)->index)
      return GST_TUNER_NORM (item->data);
  }

  return NULL;
}
Exemplo n.º 9
0
static GstTunerChannel *
gst_v4l_tuner_get_channel (GstTuner * tuner)
{
  GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
  GList *item;
  gint channel;

  /* assert that we're opened */
  g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), NULL);

  gst_v4l_get_chan_norm (v4lelement, &channel, NULL);

  for (item = v4lelement->channels; item != NULL; item = item->next) {
    if (channel == GST_V4L_TUNER_CHANNEL (item->data)->index)
      return GST_TUNER_CHANNEL (item->data);
  }

  return NULL;
}
Exemplo n.º 10
0
static gint
gst_v4l_tuner_signal_strength (GstTuner * tuner, GstTunerChannel * channel)
{
  GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
  GstV4lTunerChannel *v4lchannel = GST_V4L_TUNER_CHANNEL (channel);
  gint chan;
  guint signal = 0;

  /* assert that we're opened and that we're using a known item */
  g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), 0);
  g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
          GST_TUNER_CHANNEL_FREQUENCY), 0);
  g_return_val_if_fail (gst_v4l_tuner_contains_channel (v4lelement,
          v4lchannel), 0);

  gst_v4l_get_chan_norm (v4lelement, &chan, NULL);
  if (chan == GST_V4L_TUNER_CHANNEL (channel)->index &&
      GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
    gst_v4l_get_signal (v4lelement, v4lchannel->tuner, &signal);
  }

  return (gint) signal;
}
Exemplo n.º 11
0
static gboolean
gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps)
{
    GstV4lSrc *v4lsrc;
    guint32 fourcc;
    gint bpp, depth, w, h, palette = -1;
    const GValue *new_fps;
    gint cur_fps_n, cur_fps_d;
    GstStructure *structure;
    struct video_window *vwin;

    v4lsrc = GST_V4LSRC (src);
    vwin = &GST_V4LELEMENT (v4lsrc)->vwin;

    /* if we're not open, punt -- we'll get setcaps'd later via negotiate */
    if (!GST_V4L_IS_OPEN (v4lsrc))
        return FALSE;

    /* make sure we stop capturing and dealloc buffers */
    if (GST_V4L_IS_ACTIVE (v4lsrc)) {
        if (!gst_v4lsrc_capture_stop (v4lsrc))
            return FALSE;
        if (!gst_v4lsrc_capture_deinit (v4lsrc))
            return FALSE;
    }

    /* it's fixed, one struct */
    structure = gst_caps_get_structure (caps, 0);

    if (strcmp (gst_structure_get_name (structure), "video/x-raw-yuv") == 0)
        gst_structure_get_fourcc (structure, "format", &fourcc);
    else
        fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', ' ');

    gst_structure_get_int (structure, "width", &w);
    gst_structure_get_int (structure, "height", &h);
    new_fps = gst_structure_get_value (structure, "framerate");

    /* set framerate if it's not already correct */
    if (!gst_v4lsrc_get_fps (v4lsrc, &cur_fps_n, &cur_fps_d))
        return FALSE;

    if (new_fps) {
        GST_DEBUG_OBJECT (v4lsrc, "linking with %dx%d at %d/%d fps", w, h,
                          gst_value_get_fraction_numerator (new_fps),
                          gst_value_get_fraction_denominator (new_fps));

        if (gst_value_get_fraction_numerator (new_fps) != cur_fps_n ||
                gst_value_get_fraction_denominator (new_fps) != cur_fps_d) {
            int fps_index = (gst_value_get_fraction_numerator (new_fps) * 16) /
                            (gst_value_get_fraction_denominator (new_fps) * 15);

            GST_DEBUG_OBJECT (v4lsrc, "Trying to set fps index %d", fps_index);
            /* set bits 16 to 21 to 0 */
            vwin->flags &= (0x3F00 - 1);
            /* set bits 16 to 21 to the index */
            vwin->flags |= fps_index << 16;
            if (!gst_v4l_set_window_properties (GST_V4LELEMENT (v4lsrc))) {
                return FALSE;
            }
        }
    }

    switch (fourcc) {
    case GST_MAKE_FOURCC ('I', '4', '2', '0'):
        palette = VIDEO_PALETTE_YUV420P;
        v4lsrc->buffer_size = ((w + 1) & ~1) * ((h + 1) & ~1) * 1.5;
        break;
    case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
        palette = VIDEO_PALETTE_YUV422;
        v4lsrc->buffer_size = ((w + 1) & ~1) * h * 2;
        break;
    case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
        palette = VIDEO_PALETTE_UYVY;
        v4lsrc->buffer_size = ((w + 1) & ~1) * h * 2;
        break;
    case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
        palette = VIDEO_PALETTE_YUV411P;
        v4lsrc->buffer_size = ((w + 3) & ~3) * h * 1.5;
        break;
    case GST_MAKE_FOURCC ('Y', '4', '1', 'P'):
        palette = VIDEO_PALETTE_YUV411;
        v4lsrc->buffer_size = ((w + 3) & ~3) * h * 1.5;
        break;
    case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
        palette = VIDEO_PALETTE_YUV410P;
        v4lsrc->buffer_size = ((w + 3) & ~3) * ((h + 3) & ~3) * 1.125;
        break;
    case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
        palette = VIDEO_PALETTE_YUV422P;
        v4lsrc->buffer_size = ((w + 1) & ~1) * h * 2;
        break;
    case GST_MAKE_FOURCC ('R', 'G', 'B', ' '):
        gst_structure_get_int (structure, "depth", &depth);
        switch (depth) {
        case 15:
            palette = VIDEO_PALETTE_RGB555;
            v4lsrc->buffer_size = w * h * 2;
            break;
        case 16:
            palette = VIDEO_PALETTE_RGB565;
            v4lsrc->buffer_size = w * h * 2;
            break;
        case 24:
            gst_structure_get_int (structure, "bpp", &bpp);
            switch (bpp) {
            case 24:
                palette = VIDEO_PALETTE_RGB24;
                v4lsrc->buffer_size = w * h * 3;
                break;
            case 32:
                palette = VIDEO_PALETTE_RGB32;
                v4lsrc->buffer_size = w * h * 4;
                break;
            default:
                break;
            }
            break;
        default:
            break;
        }
        break;
    default:
        break;
    }

    if (palette == -1) {
        GST_WARNING_OBJECT (v4lsrc, "palette for fourcc %" GST_FOURCC_FORMAT
                            " is -1, refusing link", GST_FOURCC_ARGS (fourcc));
        return FALSE;
    }

    GST_DEBUG_OBJECT (v4lsrc, "trying to set_capture %dx%d, palette %d",
                      w, h, palette);
    /* this only fills in v4lsrc->mmap values */
    if (!gst_v4lsrc_set_capture (v4lsrc, w, h, palette)) {
        GST_WARNING_OBJECT (v4lsrc, "could not set_capture %dx%d, palette %d",
                            w, h, palette);
        return FALSE;
    }

    /* first try the negotiated settings using try_capture */
    if (!gst_v4lsrc_try_capture (v4lsrc, w, h, palette)) {
        GST_DEBUG_OBJECT (v4lsrc, "failed trying palette %d for %dx%d", palette,
                          w, h);
        return FALSE;
    }

    if (!gst_v4lsrc_capture_init (v4lsrc))
        return FALSE;

    if (!gst_v4lsrc_capture_start (v4lsrc))
        return FALSE;

    return TRUE;
}
Exemplo n.º 12
0
static GstCaps *
gst_v4lsrc_get_caps (GstBaseSrc * src)
{
    GstCaps *list;
    GstV4lSrc *v4lsrc = GST_V4LSRC (src);
    struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap;
    gint width = GST_V4LELEMENT (src)->vcap.minwidth;
    gint height = GST_V4LELEMENT (src)->vcap.minheight;
    gint i;
    gint fps_n, fps_d;
    GList *item;

    if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
        return gst_v4lsrc_get_any_caps ();
    }

    if (!v4lsrc->autoprobe) {
        /* FIXME: query current caps and return those, with _any appended */
        return gst_v4lsrc_get_any_caps ();
    }

    if (!v4lsrc->colorspaces) {
        GST_DEBUG_OBJECT (v4lsrc, "Checking supported palettes");
        for (i = 0; all_palettes[i] != -1; i++) {
            /* try palette out */
            if (!gst_v4lsrc_try_capture (v4lsrc, width, height, all_palettes[i]))
                continue;
            GST_DEBUG_OBJECT (v4lsrc, "Added palette %d (%s) to supported list",
                              all_palettes[i], gst_v4lsrc_palette_name (all_palettes[i]));
            v4lsrc->colorspaces = g_list_append (v4lsrc->colorspaces,
                                                 GINT_TO_POINTER (all_palettes[i]));
        }
        GST_DEBUG_OBJECT (v4lsrc, "%d palette(s) supported",
                          g_list_length (v4lsrc->colorspaces));
        if (v4lsrc->autoprobe_fps) {
            GST_DEBUG_OBJECT (v4lsrc, "autoprobing framerates");
            v4lsrc->fps_list = gst_v4lsrc_get_fps_list (v4lsrc);
        }
    }


    if (!gst_v4lsrc_get_fps (v4lsrc, &fps_n, &fps_d)) {
        fps_n = 0;
        fps_d = 1;
    }

    list = gst_caps_new_empty ();
    for (item = v4lsrc->colorspaces; item != NULL; item = item->next) {
        GstCaps *one;

        one = gst_v4lsrc_palette_to_caps (GPOINTER_TO_INT (item->data));
        if (!one) {
            GST_WARNING_OBJECT (v4lsrc, "Palette %d gave no caps\n",
                                GPOINTER_TO_INT (item->data));
            continue;
        }

        GST_DEBUG_OBJECT (v4lsrc,
                          "Device reports w: %d-%d, h: %d-%d, fps: %d/%d for palette %d",
                          vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight,
                          fps_n, fps_d, GPOINTER_TO_INT (item->data));

        if (vcap->minwidth < vcap->maxwidth) {
            gst_caps_set_simple (one, "width", GST_TYPE_INT_RANGE, vcap->minwidth,
                                 vcap->maxwidth, NULL);
        } else {
            gst_caps_set_simple (one, "width", G_TYPE_INT, vcap->minwidth, NULL);
        }
        if (vcap->minheight < vcap->maxheight) {
            gst_caps_set_simple (one, "height", GST_TYPE_INT_RANGE, vcap->minheight,
                                 vcap->maxheight, NULL);
        } else {
            gst_caps_set_simple (one, "height", G_TYPE_INT, vcap->minheight, NULL);
        }

        if (v4lsrc->autoprobe_fps) {
            GstStructure *structure = gst_caps_get_structure (one, 0);

            if (v4lsrc->fps_list) {
                gst_structure_set_value (structure, "framerate", v4lsrc->fps_list);
            } else {
                gst_structure_set (structure, "framerate", GST_TYPE_FRACTION,
                                   fps_n, fps_d, NULL);
            }
        } else {
            gst_caps_set_simple (one, "framerate", GST_TYPE_FRACTION_RANGE,
                                 1, 1, 100, 1, NULL);
        }

        GST_DEBUG_OBJECT (v4lsrc, "caps: %" GST_PTR_FORMAT, one);
        gst_caps_append (list, one);
    }

    return list;
}
Exemplo n.º 13
0
static GstPadLinkReturn
gst_v4ljpegsrc_src_link (GstPad * pad, const GstCaps * vscapslist)
{
  GstV4lJpegSrc *v4ljpegsrc;
  GstV4lSrc *v4lsrc;
  gint w, h, palette = -1;
  const GValue *fps;
  GstStructure *structure;
  gboolean was_capturing;
  struct video_window *vwin;

  v4ljpegsrc = GST_V4LJPEGSRC (gst_pad_get_parent (pad));
  v4lsrc = GST_V4LSRC (v4ljpegsrc);
  vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
  was_capturing = v4lsrc->is_capturing;

  /* in case the buffers are active (which means that we already
   * did capsnego before and didn't clean up), clean up anyways */
  if (GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc))) {
    if (was_capturing) {
      if (!gst_v4lsrc_capture_stop (v4lsrc))
        return GST_PAD_LINK_REFUSED;
    }
    if (!gst_v4lsrc_capture_deinit (v4lsrc))
      return GST_PAD_LINK_REFUSED;
  } else if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
    return GST_PAD_LINK_DELAYED;
  }

  structure = gst_caps_get_structure (vscapslist, 0);

  gst_structure_get_int (structure, "width", &w);
  gst_structure_get_int (structure, "height", &h);
  fps = gst_structure_get_value (structure, "framerate");

  GST_DEBUG_OBJECT (v4ljpegsrc, "linking with %dx%d at %d/%d fps", w, h,
      gst_value_get_fraction_numerator (fps),
      gst_value_get_fraction_denominator (fps));

  /* set framerate if it's not already correct */
  if (fps != gst_v4lsrc_get_fps (v4lsrc)) {
    int fps_index = fps / 15.0 * 16;

    GST_DEBUG_OBJECT (v4ljpegsrc, "Trying to set fps index %d", fps_index);
    /* set bits 16 to 21 to 0 */
    vwin->flags &= (0x3F00 - 1);
    /* set bits 16 to 21 to the index */
    vwin->flags |= fps_index << 16;
    if (!gst_v4l_set_window_properties (GST_V4LELEMENT (v4lsrc))) {
      return GST_PAD_LINK_DELAYED;
    }
  }

  /*
   * Try to set the camera to capture RGB24 
   */
  palette = VIDEO_PALETTE_RGB24;
  v4lsrc->buffer_size = w * h * 3;

  GST_DEBUG_OBJECT (v4ljpegsrc, "trying to set_capture %dx%d, palette %d",
      w, h, palette);
  /* this only fills in v4lsrc->mmap values */
  if (!gst_v4lsrc_set_capture (v4lsrc, w, h, palette)) {
    GST_WARNING_OBJECT (v4ljpegsrc, "could not set_capture %dx%d, palette %d",
        w, h, palette);
    return GST_PAD_LINK_REFUSED;
  }

  /* first try the negotiated settings using try_capture */
  if (!gst_v4lsrc_try_capture (v4lsrc, w, h, palette)) {
    GST_DEBUG_OBJECT (v4ljpegsrc, "failed trying palette %d for %dx%d", palette,
        w, h);
    return GST_PAD_LINK_REFUSED;
  }

  if (!gst_v4lsrc_capture_init (v4lsrc))
    return GST_PAD_LINK_REFUSED;

  if (was_capturing || GST_STATE (v4lsrc) == GST_STATE_PLAYING) {
    if (!gst_v4lsrc_capture_start (v4lsrc))
      return GST_PAD_LINK_REFUSED;
  }

  return GST_PAD_LINK_OK;
}