gstreamer调用directshow采集摄像头数据

gstreamer是个媒体引擎,可用用来开发流媒体,类似ffmpeg的filter,sink接收数据,filter处理数据(如:采集,缩放,编码等),src突出数据给链接的sink。

在Windows下,可用使用directshow来操作摄像头,gstreamer可用用利用 dshow来打开采集摄像头数据,然后推送给后面的处理filter。

gstreamer开始play会,会执行gst_element_set_state (bin, GST_STATE_PLAYING);这个函数经过一系列步骤,最终执行,

gst_element_pads_activate,应该是是遍历激活所有 pad,如下堆栈图:

static gboolean
gst_base_src_activate_push (GstPad * pad, gboolean active)
{
  GstBaseSrc *basesrc;
  GstEvent *event;

  basesrc = GST_BASE_SRC (GST_OBJECT_PARENT (pad));

  /* prepare subclass first */
  if (active) {  //激活
    GST_DEBUG_OBJECT (basesrc, "Activating in push mode");

    if (G_UNLIKELY (!basesrc->can_activate_push))
      goto no_push_activation;

    if (G_UNLIKELY (!gst_base_src_start (basesrc)))
      goto error_start;

    basesrc->priv->last_sent_eos = FALSE;
    basesrc->priv->discont = TRUE;
    gst_base_src_set_flushing (basesrc, FALSE, FALSE, FALSE, NULL);

    /* do initial seek, which will start the task */
    GST_OBJECT_LOCK (basesrc);
    event = basesrc->data.ABI.pending_seek;
    basesrc->data.ABI.pending_seek = NULL;
    GST_OBJECT_UNLOCK (basesrc);

    /* no need to unlock anything, the task is certainly
     * not running here. The perform seek code will start the task when
     * finished. */
    if (G_UNLIKELY (!gst_base_src_perform_seek (basesrc, event, FALSE)))
      goto seek_failed;

    if (event)
      gst_event_unref (event);
  } else {  //关闭
    GST_DEBUG_OBJECT (basesrc, "Deactivating in push mode");
    /* flush all */
    gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL);
    /* stop the task */
    gst_pad_stop_task (pad);
    /* now we can stop the source */
    if (G_UNLIKELY (!gst_base_src_stop (basesrc)))
      goto error_stop;
  }
  return TRUE;

  /* ERRORS */
no_push_activation:
  {
    GST_WARNING_OBJECT (basesrc, "Subclass disabled push-mode activation");
    return FALSE;
  }
error_start:
  {
    GST_WARNING_OBJECT (basesrc, "Failed to start in push mode");
    return FALSE;
  }
seek_failed:
  {
    GST_ERROR_OBJECT (basesrc, "Failed to perform initial seek");
    /* flush all */
    gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL);
    /* stop the task */
    gst_pad_stop_task (pad);
    /* Stop the basesrc */
    gst_base_src_stop (basesrc);
    if (event)
      gst_event_unref (event);
    return FALSE;
  }
error_stop:
  {
    GST_DEBUG_OBJECT (basesrc, "Failed to stop in push mode");
    return FALSE;
  }
}

如上函数的逻辑,会判断active参数,如果是1 ,调用gst_base_src_start,里面又会调用协商函数gst_base_src_negotiate,

/* default negotiation code.
 *
 * Take intersection between src and sink pads, take first
 * caps and fixate.
 */
static gboolean
gst_base_src_default_negotiate (GstBaseSrc * basesrc)
{
  GstCaps *thiscaps;
  GstCaps *caps = NULL;
  GstCaps *peercaps = NULL;
  gboolean result = FALSE;

  /* first see what is possible on our source pad */

//获取本element的src的caps,可能有很多个structrue。
  thiscaps = gst_pad_get_caps_reffed (GST_BASE_SRC_PAD (basesrc)); 
  GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
  /* nothing or anything is allowed, we're done */
  if (thiscaps == NULL || gst_caps_is_any (thiscaps))
    goto no_nego_needed;

  if (G_UNLIKELY (gst_caps_is_empty (thiscaps)))
    goto no_caps;

  /* get the peer caps */

//获取对端element的src的caps,下一个一般是个capsfilter,对camsrc的输出进行限定。
  peercaps = gst_pad_peer_get_caps_reffed (GST_BASE_SRC_PAD (basesrc));  
  GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
  if (peercaps && !gst_caps_is_any (peercaps)) {
    /* get intersection */
    caps =
        gst_caps_intersect_full (peercaps, thiscaps, GST_CAPS_INTERSECT_FIRST);
    GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, caps);
  } else {
    /* no peer, work with our own caps then */
    caps = gst_caps_copy (thiscaps);
  }
  if (peercaps)
    gst_caps_unref (peercaps);
  gst_caps_unref (thiscaps);

  //caps是个相交的结果。
  if (caps) {
    /* take first (and best, since they are sorted) possibility */
    gst_caps_truncate (caps);

    /* now fixate */
    if (!gst_caps_is_empty (caps)) {
      gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
      GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);

      if (gst_caps_is_any (caps)) {
        /* hmm, still anything, so element can do anything and
         * nego is not needed */
        result = TRUE;
      } else if (gst_caps_is_fixed (caps)) {
        /* yay, fixed caps, use those then, it's possible that the subclass does
         * not accept this caps after all and we have to fail. */

       //如果是个固定值,就设置给basesrc的src.
        result = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
      }
    }
    gst_caps_unref (caps);
  } else {
    GST_DEBUG_OBJECT (basesrc, "no common caps");
  }
  return result;

no_nego_needed:
  {
    GST_DEBUG_OBJECT (basesrc, "no negotiation needed");
    if (thiscaps)
      gst_caps_unref (thiscaps);
    return TRUE;
  }
no_caps:
  {
    GST_ELEMENT_ERROR (basesrc, STREAM, FORMAT,
        ("No supported formats found"),
        ("This element did not produce valid caps"));
    if (thiscaps)
      gst_caps_unref (thiscaps);
    return TRUE;
  }
}

在gst_pad_set_caps里一般会启动dshow,如果dshow启动失败,会导致协商失败,最终会导致播放失败。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山西茄子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值