Exemplo n.º 1
0
/**
 * gst_camerabin_create_and_add_element:
 * @bin: tries adding an element to this bin
 * @elem_name: name of the element to be created
 *
 * Creates an element according to given name and
 * adds it to given @bin. Looks for an unconnected src pad
 * from the @bin and links the element to it.
 *
 * Returns: pointer to the new element if successful, NULL otherwise.
 */
GstElement *
gst_camerabin_create_and_add_element (GstBin * bin, const gchar * elem_name)
{
  GstElement *new_elem = NULL;

  new_elem = gst_element_factory_make (elem_name, NULL);
  if (!new_elem) {
    GST_ELEMENT_ERROR (bin, CORE, MISSING_PLUGIN, (NULL),
        ("could not create \"%s\" element.", elem_name));
  } else if (!gst_camerabin_add_element (bin, new_elem)) {
    new_elem = NULL;
  }

  return new_elem;
}
Exemplo n.º 2
0
/**
 * gst_camerabin_create_and_add_element:
 * @bin: tries adding an element to this bin
 * @elem_name: name of the element to be created
 * @instance_name: name of the instance of the element to be created
 *
 * Creates an element according to given name and
 * adds it to given @bin. Looks for an unconnected src pad
 * from the @bin and links the element to it.
 *
 * Returns: pointer to the new element if successful, NULL otherwise.
 */
GstElement *
gst_camerabin_create_and_add_element (GstBin * bin, const gchar * elem_name,
    const gchar * instance_name)
{
  GstElement *new_elem;

  g_return_val_if_fail (bin, FALSE);
  g_return_val_if_fail (elem_name, FALSE);

  new_elem = gst_element_factory_make (elem_name, instance_name);
  if (!new_elem) {
    GST_ELEMENT_ERROR (bin, CORE, MISSING_PLUGIN,
        (_("Missing element '%s' - check your GStreamer installation."),
            elem_name), (NULL));
  } else if (!gst_camerabin_add_element (bin, new_elem)) {
    new_elem = NULL;
  }

  return new_elem;
}
/**
 * gst_wrapper_camera_bin_src_construct_pipeline:
 * @bcamsrc: camerasrc object
 *
 * This function creates and links the elements of the camerasrc bin
 * videosrc ! cspconv ! srcfilter ! cspconv ! capsfilter ! crop ! scale ! \
 * capsfilter ! tee name=t
 *    t. ! ... (viewfinder pad)
 *    t. ! output-selector name=outsel
 *        outsel. ! (image pad)
 *        outsel. ! (video pad)
 *
 * Returns: TRUE, if elements were successfully created, FALSE otherwise
 */
static gboolean
gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc)
{
  GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (bcamsrc);
  GstBin *cbin = GST_BIN (bcamsrc);
  GstElement *tee;
  GstElement *filter_csp;
  GstElement *src_csp;
  GstElement *capsfilter;
  gboolean ret = FALSE;
  GstPad *vf_pad;
  GstPad *tee_capture_pad;
  GstPad *src_caps_src_pad;

  /* checks and adds a new video src if needed */
  if (!check_and_replace_src (self))
    goto done;

  if (!self->elements_created) {

    GST_DEBUG_OBJECT (self, "constructing pipeline");

    if (!gst_camerabin_create_and_add_element (cbin, "videoconvert",
            "src-videoconvert"))
      goto done;

    if (self->app_vid_filter) {
      self->video_filter = gst_object_ref (self->app_vid_filter);

      if (!gst_camerabin_add_element (cbin, self->video_filter))
        goto done;
      if (!gst_camerabin_create_and_add_element (cbin, "videoconvert",
              "filter-videoconvert"))
        goto done;
    }

    if (!(self->src_filter =
            gst_camerabin_create_and_add_element (cbin, "capsfilter",
                "src-capsfilter")))
      goto done;

    /* attach to notify::caps on the first capsfilter and use a callback
     * to recalculate the zoom properties when these caps change and to
     * propagate the caps to the second capsfilter */
    src_caps_src_pad = gst_element_get_static_pad (self->src_filter, "src");
    g_signal_connect (src_caps_src_pad, "notify::caps",
        G_CALLBACK (gst_wrapper_camera_bin_src_caps_cb), self);
    gst_object_unref (src_caps_src_pad);

    if (!(self->src_zoom_crop =
            gst_camerabin_create_and_add_element (cbin, "videocrop",
                "zoom-crop")))
      goto done;
    if (!(self->src_zoom_scale =
            gst_camerabin_create_and_add_element (cbin, "videoscale",
                "zoom-scale")))
      goto done;
    if (!(self->src_zoom_filter =
            gst_camerabin_create_and_add_element (cbin, "capsfilter",
                "zoom-capsfilter")))
      goto done;

    if (!(tee =
            gst_camerabin_create_and_add_element (cbin, "tee",
                "camerasrc-tee")))
      goto done;

    /* viewfinder pad */
    vf_pad = gst_element_get_request_pad (tee, "src_%u");
    g_object_set (tee, "alloc-pad", vf_pad, NULL);
    gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), vf_pad);
    gst_object_unref (vf_pad);

    /* image/video pad from tee */
    tee_capture_pad = gst_element_get_request_pad (tee, "src_%u");

    self->output_selector =
        gst_element_factory_make ("output-selector", "outsel");
    g_object_set (self->output_selector, "pad-negotiation-mode", 2, NULL);
    gst_bin_add (GST_BIN (self), self->output_selector);
    {
      GstPad *pad = gst_element_get_static_pad (self->output_selector, "sink");

      /* check return TODO */
      gst_pad_link (tee_capture_pad, pad);
      gst_object_unref (pad);
    }
    gst_object_unref (tee_capture_pad);

    /* Create the 2 output pads for video and image */
    self->outsel_vidpad =
        gst_element_get_request_pad (self->output_selector, "src_%u");
    self->outsel_imgpad =
        gst_element_get_request_pad (self->output_selector, "src_%u");

    g_assert (self->outsel_vidpad != NULL);
    g_assert (self->outsel_imgpad != NULL);

    gst_pad_add_probe (self->outsel_imgpad, GST_PAD_PROBE_TYPE_BUFFER,
        gst_wrapper_camera_bin_src_imgsrc_probe, gst_object_ref (self),
        gst_object_unref);
    gst_pad_add_probe (self->outsel_vidpad, GST_PAD_PROBE_TYPE_BUFFER,
        gst_wrapper_camera_bin_src_vidsrc_probe, gst_object_ref (self),
        gst_object_unref);
    gst_ghost_pad_set_target (GST_GHOST_PAD (self->imgsrc),
        self->outsel_imgpad);
    gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc),
        self->outsel_vidpad);

    if (bcamsrc->mode == MODE_IMAGE) {
      g_object_set (self->output_selector, "active-pad", self->outsel_imgpad,
          NULL);
    } else {
      g_object_set (self->output_selector, "active-pad", self->outsel_vidpad,
          NULL);
    }



    gst_pad_set_active (self->vfsrc, TRUE);
    gst_pad_set_active (self->imgsrc, TRUE);    /* XXX ??? */
    gst_pad_set_active (self->vidsrc, TRUE);    /* XXX ??? */
  }

  /* Do this even if pipeline is constructed */

  if (self->video_filter) {
    /* check if we need to replace the current one */
    if (self->video_filter != self->app_vid_filter) {
      gst_bin_remove (cbin, self->video_filter);
      gst_object_unref (self->video_filter);
      self->video_filter = NULL;
      filter_csp = gst_bin_get_by_name (cbin, "filter-videoconvert");
      gst_bin_remove (cbin, filter_csp);
      gst_object_unref (filter_csp);
      filter_csp = NULL;
    }
  }

  if (!self->video_filter) {
    if (self->app_vid_filter) {
      self->video_filter = gst_object_ref (self->app_vid_filter);
      filter_csp = gst_element_factory_make ("videoconvert",
          "filter-videoconvert");
      gst_bin_add_many (cbin, self->video_filter, filter_csp, NULL);
      src_csp = gst_bin_get_by_name (cbin, "src-videoconvert");
      capsfilter = gst_bin_get_by_name (cbin, "src-capsfilter");
      if (gst_pad_is_linked (gst_element_get_static_pad (src_csp, "src")))
        gst_element_unlink (src_csp, capsfilter);
      if (!gst_element_link_many (src_csp, self->video_filter, filter_csp,
              capsfilter, NULL))
        goto done;
    }
  }
  ret = TRUE;
  self->elements_created = TRUE;
done:
  return ret;
}
Exemplo n.º 4
0
/**
 * gst_wrapper_camera_bin_src_construct_pipeline:
 * @bcamsrc: camerasrc object
 *
 * This function creates and links the elements of the camerasrc bin
 * videosrc ! cspconv ! capsfilter ! crop ! scale ! capsfilter ! tee name=t !
 *    t. ! ... (viewfinder pad)
 *    t. ! output-selector name=outsel
 *        outsel. ! (image pad)
 *        outsel. ! (video pad)
 *
 * Returns: TRUE, if elements were successfully created, FALSE otherwise
 */
static gboolean
gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc)
{
  GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (bcamsrc);
  GstBin *cbin = GST_BIN (bcamsrc);
  GstElement *tee;
  gboolean ret = FALSE;
  GstElement *videoscale;
  GstPad *vf_pad;
  GstPad *tee_capture_pad;

  if (self->elements_created)
    return TRUE;

  GST_DEBUG_OBJECT (self, "constructing pipeline");

  /* Add application set or default video src element */
  if (!(self->src_vid_src = gst_camerabin_setup_default_element (cbin,
              self->app_vid_src, "autovideosrc", DEFAULT_VIDEOSRC))) {
    self->src_vid_src = NULL;
    goto done;
  } else {
    if (!gst_camerabin_add_element (cbin, self->src_vid_src)) {
      goto done;
    }
  }
  /* we lost the reference */
  self->app_vid_src = NULL;

  /* add a buffer probe to the src elemento to drop EOS from READY->NULL */
  {
    GstPad *pad;
    pad = gst_element_get_static_pad (self->src_vid_src, "src");

    self->src_event_probe_id = gst_pad_add_event_probe (pad,
        (GCallback) src_event_probe, self);
    gst_object_unref (pad);
  }

  if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace"))
    goto done;

  if (!(self->src_filter =
          gst_camerabin_create_and_add_element (cbin, "capsfilter")))
    goto done;

  if (!(self->src_zoom_crop =
          gst_camerabin_create_and_add_element (cbin, "videocrop")))
    goto done;
  if (!(self->src_zoom_scale =
          gst_camerabin_create_and_add_element (cbin, "videoscale")))
    goto done;
  if (!(self->src_zoom_filter =
          gst_camerabin_create_and_add_element (cbin, "capsfilter")))
    goto done;

  if (!(tee = gst_camerabin_create_and_add_element (cbin, "tee")))
    goto done;

  /* viewfinder pad */
  vf_pad = gst_element_get_request_pad (tee, "src%d");
  g_object_set (tee, "alloc-pad", vf_pad, NULL);
  gst_object_unref (vf_pad);

  /* the viewfinder should always work, so we add some converters to it */
  if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace"))
    goto done;
  if (!(videoscale = gst_camerabin_create_and_add_element (cbin, "videoscale")))
    goto done;

  /* image/video pad from tee */
  tee_capture_pad = gst_element_get_request_pad (tee, "src%d");

  self->output_selector =
      gst_element_factory_make ("output-selector", "outsel");
  gst_bin_add (GST_BIN (self), self->output_selector);
  {
    GstPad *pad = gst_element_get_static_pad (self->output_selector, "sink");

    /* check return TODO */
    gst_pad_link (tee_capture_pad, pad);
    gst_object_unref (pad);
  }
  gst_object_unref (tee_capture_pad);

  /* Create the 2 output pads for video and image */
  self->outsel_vidpad =
      gst_element_get_request_pad (self->output_selector, "src%d");
  self->outsel_imgpad =
      gst_element_get_request_pad (self->output_selector, "src%d");

  g_assert (self->outsel_vidpad != NULL);
  g_assert (self->outsel_imgpad != NULL);

  gst_pad_add_buffer_probe (self->outsel_imgpad,
      G_CALLBACK (gst_wrapper_camera_bin_src_imgsrc_probe), self);
  gst_pad_add_buffer_probe (self->outsel_vidpad,
      G_CALLBACK (gst_wrapper_camera_bin_src_vidsrc_probe), self);
  gst_ghost_pad_set_target (GST_GHOST_PAD (self->imgsrc), self->outsel_imgpad);
  gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), self->outsel_vidpad);

  if (bcamsrc->mode == MODE_IMAGE) {
    g_object_set (self->output_selector, "active-pad", self->outsel_imgpad,
        NULL);
  } else {
    g_object_set (self->output_selector, "active-pad", self->outsel_vidpad,
        NULL);
  }

  /* hook-up the vf ghostpad */
  vf_pad = gst_element_get_static_pad (videoscale, "src");
  gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), vf_pad);
  gst_object_unref (vf_pad);

  gst_pad_set_active (self->vfsrc, TRUE);
  gst_pad_set_active (self->imgsrc, TRUE);      /* XXX ??? */
  gst_pad_set_active (self->vidsrc, TRUE);      /* XXX ??? */

  ret = TRUE;
  self->elements_created = TRUE;
done:
  return ret;
}
Exemplo n.º 5
0
/**
 * gst_wrapper_camera_bin_src_construct_pipeline:
 * @bcamsrc: camerasrc object
 *
 * This function creates and links the elements of the camerasrc bin
 * videosrc ! cspconv ! srcfilter ! cspconv ! capsfilter ! crop ! scale ! \
 * capsfilter ! tee name=t
 *    t. ! ... (viewfinder pad)
 *    t. ! output-selector name=outsel
 *        outsel. ! (image pad)
 *        outsel. ! (video pad)
 *
 * Returns: TRUE, if elements were successfully created, FALSE otherwise
 */
static gboolean
gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc)
{
  GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (bcamsrc);
  GstBin *cbin = GST_BIN (bcamsrc);
  GstElement *tee;
  GstElement *filter_csp;
  GstElement *src_csp;
  GstElement *capsfilter;
  gboolean ret = FALSE;
  GstPad *vf_pad;
  GstPad *tee_capture_pad;
  GstPad *src_caps_src_pad;

  if (!self->elements_created) {

    GST_DEBUG_OBJECT (self, "constructing pipeline");

    /* Add application set or default video src element */
    if (!(self->src_vid_src = gst_camerabin_setup_default_element (cbin,
                self->app_vid_src, "autovideosrc", DEFAULT_VIDEOSRC,
                "camerasrc-real-src"))) {
      self->src_vid_src = NULL;
      goto done;
    } else {
      if (!gst_camerabin_add_element (cbin, self->src_vid_src)) {
        goto done;
      }
    }
    /* we lost the reference */
    self->app_vid_src = NULL;

    /* we listen for changes to max-zoom in the video src so that
     * we can proxy them to the basecamerasrc property */
    if (g_object_class_find_property (G_OBJECT_GET_CLASS (bcamsrc), "max-zoom")) {
      g_signal_connect (G_OBJECT (self->src_vid_src), "notify::max-zoom",
          (GCallback) gst_wrapper_camera_bin_src_max_zoom_cb, bcamsrc);
    }

    /* add a buffer probe to the src elemento to drop EOS from READY->NULL */
    {
      GstPad *pad;
      pad = gst_element_get_static_pad (self->src_vid_src, "src");

      self->src_event_probe_id = gst_pad_add_event_probe (pad,
          (GCallback) gst_wrapper_camera_src_src_event_probe, self);
      gst_object_unref (pad);
    }

    if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace",
            "src-colorspace"))
      goto done;

    if (!(self->src_filter =
            gst_camerabin_create_and_add_element (cbin, "capsfilter",
                "src-capsfilter")))
      goto done;

    /* attach to notify::caps on the first capsfilter and use a callback
     * to recalculate the zoom properties when these caps change and to
     * propagate the caps to the second capsfilter */
    src_caps_src_pad = gst_element_get_static_pad (self->src_filter, "src");
    g_signal_connect (src_caps_src_pad, "notify::caps",
        G_CALLBACK (gst_wrapper_camera_bin_src_caps_cb), self);
    gst_object_unref (src_caps_src_pad);

    if (!(self->src_zoom_crop =
            gst_camerabin_create_and_add_element (cbin, "videocrop",
                "zoom-crop")))
      goto done;
    if (!(self->src_zoom_scale =
            gst_camerabin_create_and_add_element (cbin, "videoscale",
                "zoom-scale")))
      goto done;
    if (!(self->src_zoom_filter =
            gst_camerabin_create_and_add_element (cbin, "capsfilter",
                "zoom-capsfilter")))
      goto done;

    if (!(tee =
            gst_camerabin_create_and_add_element (cbin, "tee",
                "camerasrc-tee")))
      goto done;

    /* viewfinder pad */
    vf_pad = gst_element_get_request_pad (tee, "src%d");
    g_object_set (tee, "alloc-pad", vf_pad, NULL);
    gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), vf_pad);
    gst_object_unref (vf_pad);

    /* image/video pad from tee */
    tee_capture_pad = gst_element_get_request_pad (tee, "src%d");

    self->output_selector =
        gst_element_factory_make ("output-selector", "outsel");
    g_object_set (self->output_selector, "pad-negotiation-mode", 0, NULL);
    gst_bin_add (GST_BIN (self), self->output_selector);
    {
      GstPad *pad = gst_element_get_static_pad (self->output_selector, "sink");

      /* check return TODO */
      gst_pad_link (tee_capture_pad, pad);
      gst_object_unref (pad);
    }
    gst_object_unref (tee_capture_pad);

    /* Create the 2 output pads for video and image */
    self->outsel_vidpad =
        gst_element_get_request_pad (self->output_selector, "src%d");
    self->outsel_imgpad =
        gst_element_get_request_pad (self->output_selector, "src%d");

    g_assert (self->outsel_vidpad != NULL);
    g_assert (self->outsel_imgpad != NULL);

    gst_pad_add_buffer_probe (self->outsel_imgpad,
        G_CALLBACK (gst_wrapper_camera_bin_src_imgsrc_probe), self);
    gst_pad_add_buffer_probe (self->outsel_vidpad,
        G_CALLBACK (gst_wrapper_camera_bin_src_vidsrc_probe), self);
    gst_ghost_pad_set_target (GST_GHOST_PAD (self->imgsrc),
        self->outsel_imgpad);
    gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc),
        self->outsel_vidpad);

    if (bcamsrc->mode == MODE_IMAGE) {
      g_object_set (self->output_selector, "active-pad", self->outsel_imgpad,
          NULL);
    } else {
      g_object_set (self->output_selector, "active-pad", self->outsel_vidpad,
          NULL);
    }



    gst_pad_set_active (self->vfsrc, TRUE);
    gst_pad_set_active (self->imgsrc, TRUE);    /* XXX ??? */
    gst_pad_set_active (self->vidsrc, TRUE);    /* XXX ??? */
  }

  /* Do this even if pipeline is constructed */

  if (self->video_filter) {
    /* check if we need to replace the current one */
    if (self->video_filter != self->app_vid_filter) {
      gst_bin_remove (cbin, self->video_filter);
      gst_object_unref (self->video_filter);
      self->video_filter = NULL;
      filter_csp = gst_bin_get_by_name (cbin, "filter-colorspace");
      gst_bin_remove (cbin, filter_csp);
      gst_object_unref (filter_csp);
      filter_csp = NULL;
    }
  }

  if (!self->video_filter) {
    if (self->app_vid_filter) {
      self->video_filter = gst_object_ref (self->app_vid_filter);
      filter_csp = gst_element_factory_make ("ffmpegcolorspace",
          "filter-colorspace");
      gst_bin_add_many (cbin, self->video_filter, filter_csp, NULL);
      src_csp = gst_bin_get_by_name (cbin, "src-colorspace");
      capsfilter = gst_bin_get_by_name (cbin, "src-capsfilter");
      if (gst_pad_is_linked (gst_element_get_static_pad (src_csp, "src")))
        gst_element_unlink (src_csp, capsfilter);
      if (!gst_element_link_many (src_csp, self->video_filter, filter_csp,
              capsfilter, NULL))
        goto done;
    }
  }
  ret = TRUE;
  self->elements_created = TRUE;
done:
  return ret;
}