⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gstbasetransform.c

📁 gnash 在pc和嵌入式下开发需要的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
  gboolean ret;  klass = GST_BASE_TRANSFORM_GET_CLASS (trans);  GST_DEBUG_OBJECT (trans, "asked to transform size %d for caps %"      GST_PTR_FORMAT " to size for caps %" GST_PTR_FORMAT " in direction %s",      size, caps, othercaps, direction == GST_PAD_SRC ? "SRC" : "SINK");  /* if there is a custom transform function, use this */  if (klass->transform_size) {    ret = klass->transform_size (trans, direction, caps, size, othercaps,        othersize);  } else {    if (!gst_base_transform_get_unit_size (trans, caps, &inunitsize))      goto no_in_size;    GST_DEBUG_OBJECT (trans, "input size %d, input unit size %d", size,        inunitsize);    if (inunitsize == 0 || (size % inunitsize != 0))      goto no_multiple;    units = size / inunitsize;    if (!gst_base_transform_get_unit_size (trans, othercaps, &outunitsize))      goto no_out_size;    *othersize = units * outunitsize;    GST_DEBUG_OBJECT (trans, "transformed size to %d", *othersize);    ret = TRUE;  }  return ret;  /* ERRORS */no_in_size:  {    GST_DEBUG_OBJECT (trans, "could not get in_size");    g_warning ("could not get in_size");    return FALSE;  }no_multiple:  {    GST_DEBUG_OBJECT (trans, "Size %u is not a multiple of unit size %u", size,        inunitsize);    g_warning ("Size %u is not a multiple of unit size %u", size, inunitsize);    return FALSE;  }no_out_size:  {    GST_DEBUG_OBJECT (trans, "could not get out_size");    g_warning ("could not get out_size");    return FALSE;  }}static GstCaps *gst_base_transform_getcaps (GstPad * pad){  GstBaseTransform *trans;  GstPad *otherpad;  GstCaps *caps;  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));  otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;  /* we can do what the peer can */  caps = gst_pad_peer_get_caps (otherpad);  if (caps) {    GstCaps *temp;    const GstCaps *templ;    GST_DEBUG_OBJECT (pad, "peer caps  %" GST_PTR_FORMAT, caps);    /* filtered against our padtemplate */    templ = gst_pad_get_pad_template_caps (otherpad);    GST_DEBUG_OBJECT (pad, "our template  %" GST_PTR_FORMAT, templ);    temp = gst_caps_intersect (caps, templ);    GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);    gst_caps_unref (caps);    /* then see what we can transform this to */    caps = gst_base_transform_transform_caps (trans,        GST_PAD_DIRECTION (otherpad), temp);    GST_DEBUG_OBJECT (pad, "transformed  %" GST_PTR_FORMAT, caps);    gst_caps_unref (temp);    if (caps == NULL)      goto done;    /* and filter against the template again */    templ = gst_pad_get_pad_template_caps (pad);    GST_DEBUG_OBJECT (pad, "our template  %" GST_PTR_FORMAT, templ);    temp = gst_caps_intersect (caps, templ);    GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);    gst_caps_unref (caps);    /* this is what we can do */    caps = temp;  } else {    /* no peer, our padtemplate is enough then */    caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));  }done:  GST_DEBUG_OBJECT (trans, "returning  %" GST_PTR_FORMAT, caps);  gst_object_unref (trans);  return caps;}/* function triggered when the in and out caps are negotiated and need * to be configured in the subclass. */static gbooleangst_base_transform_configure_caps (GstBaseTransform * trans, GstCaps * in,    GstCaps * out){  gboolean ret = TRUE;  GstBaseTransformClass *klass;  klass = GST_BASE_TRANSFORM_GET_CLASS (trans);  /* clear the cache */  gst_caps_replace (&trans->cache_caps1, NULL);  gst_caps_replace (&trans->cache_caps2, NULL);  /* If we've a transform_ip method and same input/output caps, set in_place   * by default. If for some reason the sub-class prefers using a transform   * function, it can clear the in place flag in the set_caps */  gst_base_transform_set_in_place (trans,      klass->transform_ip && trans->have_same_caps);  /* Set the passthrough if the class wants passthrough_on_same_caps   * and we have the same caps on each pad */  if (klass->passthrough_on_same_caps)    gst_base_transform_set_passthrough (trans, trans->have_same_caps);  /* now configure the element with the caps */  if (klass->set_caps) {    GST_DEBUG_OBJECT (trans, "Calling set_caps method to setup caps");    ret = klass->set_caps (trans, in, out);  }  trans->negotiated = ret;  return ret;}/* called when new caps arrive on the sink or source pad */static gbooleangst_base_transform_setcaps (GstPad * pad, GstCaps * caps){  GstBaseTransform *trans;  GstBaseTransformClass *klass;  GstPad *otherpad, *otherpeer;  GstCaps *othercaps = NULL;  gboolean ret = TRUE;  gboolean peer_checked = FALSE;  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));  klass = GST_BASE_TRANSFORM_GET_CLASS (trans);  otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;  otherpeer = gst_pad_get_peer (otherpad);  /* if we get called recursively, we bail out now to avoid an   * infinite loop. */  if (GST_PAD_IS_IN_SETCAPS (otherpad))    goto done;  /* caps must be fixed here */  if (!gst_caps_is_fixed (caps))    goto unfixed_caps;  /* see how we can transform the input caps. */  othercaps = gst_base_transform_transform_caps (trans,      GST_PAD_DIRECTION (pad), caps);  /* The caps we can actually output is the intersection of the transformed   * caps with the pad template for the pad */  if (othercaps) {    GstCaps *intersect;    const GstCaps *templ_caps;    templ_caps = gst_pad_get_pad_template_caps (otherpad);    intersect = gst_caps_intersect (othercaps, templ_caps);    gst_caps_unref (othercaps);    othercaps = intersect;  }  /* check if transform is empty */  if (!othercaps || gst_caps_is_empty (othercaps))    goto no_transform;  /* if the othercaps are not fixed, we need to fixate them, first attempt   * is by attempting passthrough if the othercaps are a superset of caps. */  if (!gst_caps_is_fixed (othercaps)) {    GstCaps *temp;    GST_DEBUG_OBJECT (trans,        "transform returned non fixed  %" GST_PTR_FORMAT, othercaps);    /* see if the target caps are a superset of the source caps, in this     * case we can try to perform passthrough */    temp = gst_caps_intersect (othercaps, caps);    GST_DEBUG_OBJECT (trans, "intersect returned %" GST_PTR_FORMAT, temp);    if (temp) {      if (!gst_caps_is_empty (temp) && otherpeer) {        GST_DEBUG_OBJECT (trans, "try passthrough with %" GST_PTR_FORMAT, caps);        /* try passthrough. we know it's fixed, because caps is fixed */        if (gst_pad_accept_caps (otherpeer, caps)) {          GST_DEBUG_OBJECT (trans, "peer accepted %" GST_PTR_FORMAT, caps);          /* peer accepted unmodified caps, we free the original non-fixed           * caps and work with the passthrough caps */          gst_caps_unref (othercaps);          othercaps = gst_caps_ref (caps);          /* mark that we checked othercaps with the peer, this           * makes sure we don't call accept_caps again with these same           * caps */          peer_checked = TRUE;        } else {          GST_DEBUG_OBJECT (trans,              "peer did not accept %" GST_PTR_FORMAT, caps);        }      }      gst_caps_unref (temp);    }  }  /* second attempt at fixation is done by intersecting with   * the peer caps */  if (!gst_caps_is_fixed (othercaps) && otherpeer) {    /* intersect against what the peer can do */    GstCaps *peercaps;    GstCaps *intersect;    GST_DEBUG_OBJECT (trans, "othercaps now %" GST_PTR_FORMAT, othercaps);    peercaps = gst_pad_get_caps (otherpeer);    intersect = gst_caps_intersect (peercaps, othercaps);    gst_caps_unref (peercaps);    gst_caps_unref (othercaps);    othercaps = intersect;    peer_checked = FALSE;    GST_DEBUG_OBJECT (trans,        "filtering against peer yields %" GST_PTR_FORMAT, othercaps);  }  if (gst_caps_is_empty (othercaps))    goto no_transform_possible;  /* third attempt at fixation, call the fixate vmethod and   * ultimately call the pad fixate function. */  if (!gst_caps_is_fixed (othercaps)) {    GstCaps *temp;    GST_DEBUG_OBJECT (trans,        "trying to fixate %" GST_PTR_FORMAT " on pad %s:%s",        othercaps, GST_DEBUG_PAD_NAME (otherpad));    /* since we have no other way to fixate left, we might as well just take     * the first of the caps list and fixate that */    /* FIXME: when fixating using the vmethod, it might make sense to fixate     * each of the caps; but Wim doesn't see a use case for that yet */    temp = gst_caps_copy_nth (othercaps, 0);    gst_caps_unref (othercaps);    othercaps = temp;    peer_checked = FALSE;    if (klass->fixate_caps) {      GST_DEBUG_OBJECT (trans, "trying to fixate %" GST_PTR_FORMAT          " using caps %" GST_PTR_FORMAT          " on pad %s:%s using fixate_caps vmethod", othercaps, caps,          GST_DEBUG_PAD_NAME (otherpad));      klass->fixate_caps (trans, GST_PAD_DIRECTION (pad), caps, othercaps);    }    /* if still not fixed, no other option but to let the default pad fixate     * function do its job */    if (!gst_caps_is_fixed (othercaps)) {      GST_DEBUG_OBJECT (trans, "trying to fixate %" GST_PTR_FORMAT          " on pad %s:%s using gst_pad_fixate_caps", othercaps,          GST_DEBUG_PAD_NAME (otherpad));      gst_pad_fixate_caps (otherpad, othercaps);    }    GST_DEBUG_OBJECT (trans, "after fixating %" GST_PTR_FORMAT, othercaps);  }  /* caps should be fixed now, if not we have to fail. */  if (!gst_caps_is_fixed (othercaps))    goto could_not_fixate;  /* and peer should accept, don't check again if we already checked the   * othercaps against the peer. */  if (!peer_checked && otherpeer && !gst_pad_accept_caps (otherpeer, othercaps))    goto peer_no_accept;  GST_DEBUG_OBJECT (trans, "Input caps were %" GST_PTR_FORMAT      ", and got final caps %" GST_PTR_FORMAT, caps, othercaps);  trans->have_same_caps = gst_caps_is_equal (caps, othercaps);  GST_DEBUG_OBJECT (trans, "have_same_caps: %d", trans->have_same_caps);  /* see if we have to configure the element now */  if (!trans->delay_configure) {    GstCaps *incaps, *outcaps;    /* make sure in and out caps are correct */    if (pad == trans->sinkpad) {      incaps = caps;      outcaps = othercaps;    } else {      incaps = othercaps;      outcaps = caps;    }    /* call configure now */    if (!(ret = gst_base_transform_configure_caps (trans, incaps, outcaps)))      goto failed_configure;  } else {    /* set pending configure, the configure will happen later with the     * caps we set on the pads above. */    trans->pending_configure = TRUE;  }  /* we know this will work, we implement the setcaps */  gst_pad_set_caps (otherpad, othercaps);  if (pad == trans->srcpad && trans->priv->pad_mode == GST_ACTIVATE_PULL) {    ret &= gst_pad_set_caps (otherpeer, othercaps);    if (!ret) {      GST_INFO_OBJECT (trans, "otherpeer setcaps(%" GST_PTR_FORMAT ") failed",          othercaps);    }  }done:  if (otherpeer)    gst_object_unref (otherpeer);  if (othercaps)    gst_caps_unref (othercaps);  trans->negotiated = ret;  gst_object_unref (trans);  return ret;  /* ERRORS */unfixed_caps:  {    GST_DEBUG_OBJECT (trans, "caps are not fixed  %" GST_PTR_FORMAT, caps);    ret = FALSE;    goto done;  }no_transform:  {    GST_DEBUG_OBJECT (trans,        "transform returned useless  %" GST_PTR_FORMAT, othercaps);    ret = FALSE;    goto done;  }no_transform_possible:  {    GST_DEBUG_OBJECT (trans,        "transform could not transform %" GST_PTR_FORMAT        " in anything we support", caps);    ret = FALSE;    goto done;  }could_not_fixate:  {    GST_ERROR_OBJECT (trans, "FAILED to fixate %" GST_PTR_FORMAT, othercaps);    ret = FALSE;    goto done;  }peer_no_accept:  {    GST_DEBUG_OBJECT (trans, "FAILED to get peer of %" GST_PTR_FORMAT        " to accept %" GST_PTR_FORMAT, otherpad, othercaps);    ret = FALSE;    goto done;  }failed_configure:  {    GST_DEBUG_OBJECT (trans, "FAILED to configure caps %" GST_PTR_FORMAT        " to accept %" GST_PTR_FORMAT, otherpad, othercaps);    ret = FALSE;    goto done;  }}/* Allocate a buffer using gst_pad_alloc_buffer * * This function does not do renegotiation on the source pad * * The output buffer is always writable. outbuf can be equal to * inbuf, the caller should be prepared for this and perform  * appropriate refcounting. */static GstFlowReturngst_base_transform_prepare_output_buffer (GstBaseTransform * trans,    GstBuffer * in_buf, gint out_size, GstCaps * out_caps, GstBuffer ** out_buf){  GstBaseTransformClass *bclass;  GstFlowReturn ret = GST_FLOW_OK;  gboolean copy_inbuf = FALSE;  bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);  /* we cannot reconfigure the element yet as we are still processing   * the old buffer. We will therefore delay the reconfiguration of the   * element until we have processed this last buffer. */  trans->delay_configure = TRUE;  /* out_caps is the caps of the src pad gathered through the GST_PAD_CAPS      macro. If a set_caps occurs during this function this caps will become     invalid. We want to keep them during preparation of the output buffer. */  if (out_caps)    gst_caps_ref (out_caps);  /* see if the subclass wants to alloc a buffer */  if (bclass->prepare_output_buffer) {    ret =        bclass->prepare_output_buffer (trans, in_buf, out_size, out_caps,        out_buf);    if (ret != GST_FLOW_OK)      goto done;    /* decrease refcount again if vmethod returned refcounted in_buf. This     * is because we need to make sure that the buffer is writable for the     * in_place transform. The docs of the vmethod say that you should return     * a reffed inbuf, which is exactly what we don't want :), oh well.. */    if (in_buf == *out_buf)      gst_buffer_unref (in_buf);  }  /* See if we want to prepare the buffer for in place output */  if (*out_buf == NULL && GST_BUFFER_SIZE (in_buf) == out_size      && bclass->transform_ip) {    if (gst_buffer_is_writable (in_buf)) {      if (trans->have_same_caps) {        /* Input buffer is already writable and caps are the same, return input as         * output buffer. We don't take an additional ref since that would make the         * output buffer not writable anymore. Caller should be prepared to deal         * with proper refcounting of input/output buffers. */        *out_buf = in_buf;        GST_LOG_OBJECT (trans, "reuse input buffer");      } else {        /* Writable buffer, but need to change caps => subbuffer */        *out_buf = gst_buffer_create_sub (in_buf, 0, GST_BUFFER_SIZE (in_buf));        gst_caps_replace (&GST_BUFFER_CAPS (*out_buf), out_caps);        GST_LOG_OBJECT (trans, "created sub-buffer of input buffer");      }      /* we are done now */      goto done;    } else {      /* Make a writable buffer below and copy the data */      copy_inbuf = TRUE;      GST_LOG_OBJECT (trans, "need to copy input buffer to new output buffer");    }  }  if (*out_buf == NULL) {    /* Sub-class didn't already provide a buffer for us. Make one */    ret = gst_pad_alloc_buffer (trans->srcpad,        GST_BUFFER_OFFSET (in_buf), out_size, out_caps, out_buf);    if (ret != GST_FLOW_OK || *out_buf == NULL)      goto done;    /* allocated buffer could be of different caps than what we requested */    if (G_UNLIKELY (!gst_caps_is_equal (out_caps, GST_BUFFER_CAPS (*out_buf)))) {      /* FIXME, it is possible we can reconfigure the transform with new caps at this       * point but for now we just create a buffer ourselves */      gst_buffer_unref (*out_buf);      *out_buf = gst_buffer_new_and_alloc (out_size);      gst_buffer_set_caps (*out_buf, out_caps);    }  }  /* If the output buffer metadata is modifiable, copy timestamps and   * buffer flags */  if (*out_buf != in_buf && gst_buffer_is_metadata_writable (*out_buf)) {    if (copy_inbuf && gst_buffer_is_writable (*out_buf))      memcpy (GST_BUFFER_DATA (*out_buf), GST_BUFFER_DATA (in_buf), out_size);    gst_buffer_copy_metadata (*out_buf, in_buf,        GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -