Ejemplo n.º 1
0
static GstCaps *
gst_video_rate_transform_caps (GstBaseTransform * trans,
    GstPadDirection direction, GstCaps * caps, GstCaps * filter)
{
  GstVideoRate *videorate = GST_VIDEO_RATE (trans);
  GstCaps *ret;
  GstStructure *s, *s1, *s2, *s3 = NULL;
  int maxrate = g_atomic_int_get (&videorate->max_rate);
  gint i;

  ret = gst_caps_new_empty ();

  for (i = 0; i < gst_caps_get_size (caps); i++) {
    s = gst_caps_get_structure (caps, i);

    s1 = gst_structure_copy (s);

    if (videorate->updating_caps && direction == GST_PAD_SINK) {
      GST_INFO_OBJECT (trans,
          "Only updating caps %" GST_PTR_FORMAT " with framerate" " %d/%d",
          caps, videorate->to_rate_numerator, videorate->to_rate_denominator);

      gst_structure_set (s1, "framerate", GST_TYPE_FRACTION,
          videorate->to_rate_numerator, videorate->to_rate_denominator, NULL);
      ret = gst_caps_merge_structure (ret, s1);

      continue;
    }

    s2 = gst_structure_copy (s);
    s3 = NULL;

    if (videorate->drop_only) {
      gint min_num = 0, min_denom = 1;
      gint max_num = G_MAXINT, max_denom = 1;

      /* Clamp the caps to our maximum rate as the first caps if possible */
      if (!gst_video_max_rate_clamp_structure (s1, maxrate,
              &min_num, &min_denom, &max_num, &max_denom)) {
        min_num = 0;
        min_denom = 1;
        max_num = maxrate;
        max_denom = 1;

        /* clamp wouldn't be a real subset of 1..maxrate, in this case the sink
         * caps should become [1..maxrate], [1..maxint] and the src caps just
         * [1..maxrate].  In case there was a caps incompatibility things will
         * explode later as appropriate :)
         *
         * In case [X..maxrate] == [X..maxint], skip as we'll set it later
         */
        if (direction == GST_PAD_SRC && maxrate != G_MAXINT)
          gst_structure_set (s1, "framerate", GST_TYPE_FRACTION_RANGE,
              min_num, min_denom, maxrate, 1, NULL);
        else {
          gst_structure_free (s1);
          s1 = NULL;
        }
      }

      if (direction == GST_PAD_SRC) {
        /* We can accept anything as long as it's at least the minimal framerate
         * the the sink needs */
        gst_structure_set (s2, "framerate", GST_TYPE_FRACTION_RANGE,
            min_num, min_denom, G_MAXINT, 1, NULL);

        /* Also allow unknown framerate, if it isn't already */
        if (min_num != 0 || min_denom != 1) {
          s3 = gst_structure_copy (s);
          gst_structure_set (s3, "framerate", GST_TYPE_FRACTION, 0, 1, NULL);
        }
      } else if (max_num != 0 || max_denom != 1) {
        /* We can provide everything upto the maximum framerate at the src */
        gst_structure_set (s2, "framerate", GST_TYPE_FRACTION_RANGE,
            0, 1, max_num, max_denom, NULL);
      }
    } else if (direction == GST_PAD_SINK) {
      gint min_num = 0, min_denom = 1;
      gint max_num = G_MAXINT, max_denom = 1;

      if (!gst_video_max_rate_clamp_structure (s1, maxrate,
              &min_num, &min_denom, &max_num, &max_denom)) {
        gst_structure_free (s1);
        s1 = NULL;
      }
      gst_structure_set (s2, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1,
          maxrate, 1, NULL);
    } else {
      /* set the framerate as a range */
      gst_structure_set (s2, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1,
          G_MAXINT, 1, NULL);
    }
    if (s1 != NULL)
      ret = gst_caps_merge_structure_full (ret, s1,
          gst_caps_features_copy (gst_caps_get_features (caps, i)));
    ret = gst_caps_merge_structure_full (ret, s2,
        gst_caps_features_copy (gst_caps_get_features (caps, i)));
    if (s3 != NULL)
      ret = gst_caps_merge_structure_full (ret, s3,
          gst_caps_features_copy (gst_caps_get_features (caps, i)));
  }
  if (filter) {
    GstCaps *intersection;

    intersection =
        gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
    gst_caps_unref (ret);
    ret = intersection;
  }
  return ret;
}
static GstCaps *
gst_play_sink_convert_bin_getcaps (GstPad * pad, GstCaps * filter)
{
  GstPlaySinkConvertBin *self =
      GST_PLAY_SINK_CONVERT_BIN (gst_pad_get_parent (pad));
  GstCaps *ret;
  GstPad *otherpad, *peer;

  GST_PLAY_SINK_CONVERT_BIN_LOCK (self);
  if (pad == self->srcpad) {
    otherpad = self->sinkpad;
  } else if (pad == self->sinkpad) {
    otherpad = self->srcpad;
  } else {
    GST_ERROR_OBJECT (pad, "Not one of our pads");
    otherpad = NULL;
  }

  if (otherpad) {
    peer = gst_pad_get_peer (otherpad);
    if (peer) {
      GstCaps *peer_caps;
      GstCaps *downstream_filter = NULL;

      /* Add all the caps that we can convert to to the filter caps,
       * otherwise downstream might just return EMPTY caps because
       * it doesn't handle the filter caps but we could still convert
       * to these caps */
      if (filter) {
        guint i, n;

        downstream_filter = gst_caps_new_empty ();

        /* Intersect raw video caps in the filter caps with the converter
         * caps. This makes sure that we don't accept raw video that we
         * can't handle, e.g. because of caps features */
        n = gst_caps_get_size (filter);
        for (i = 0; i < n; i++) {
          GstStructure *s;
          GstCaps *tmp, *tmp2;

          s = gst_structure_copy (gst_caps_get_structure (filter, i));
          if (gst_structure_has_name (s,
                  self->audio ? "audio/x-raw" : "video/x-raw")) {
            tmp = gst_caps_new_full (s, NULL);
            tmp2 = gst_caps_intersect (tmp, self->converter_caps);
            gst_caps_append (downstream_filter, tmp2);
            gst_caps_unref (tmp);
          } else {
            gst_caps_append_structure (downstream_filter, s);
          }
        }
        downstream_filter =
            gst_caps_merge (downstream_filter,
            gst_caps_ref (self->converter_caps));
      }

      peer_caps = gst_pad_query_caps (peer, downstream_filter);
      if (downstream_filter)
        gst_caps_unref (downstream_filter);
      gst_object_unref (peer);
      if (self->converter_caps && is_raw_caps (peer_caps, self->audio)) {
        GstCaps *converter_caps = gst_caps_ref (self->converter_caps);
        GstCapsFeatures *cf;
        GstStructure *s;
        guint i, n;

        ret = gst_caps_make_writable (peer_caps);

        /* Filter out ANY capsfeatures from the converter caps. We can't
         * convert to ANY capsfeatures, they are only there so that we
         * can passthrough whatever downstream can support... but we
         * definitely don't want to return them here
         */
        n = gst_caps_get_size (converter_caps);
        for (i = 0; i < n; i++) {
          s = gst_caps_get_structure (converter_caps, i);
          cf = gst_caps_get_features (converter_caps, i);

          if (cf && gst_caps_features_is_any (cf))
            continue;
          ret =
              gst_caps_merge_structure_full (ret, gst_structure_copy (s),
              (cf ? gst_caps_features_copy (cf) : NULL));
        }
        gst_caps_unref (converter_caps);
      } else {
        ret = peer_caps;
      }
    } else {
      ret = gst_caps_ref (self->converter_caps);
    }
    GST_PLAY_SINK_CONVERT_BIN_FILTER_CAPS (filter, ret);

  } else {
    ret = filter ? gst_caps_ref (filter) : gst_caps_new_any ();
  }
  GST_PLAY_SINK_CONVERT_BIN_UNLOCK (self);

  gst_object_unref (self);

  GST_DEBUG_OBJECT (pad, "Returning caps %" GST_PTR_FORMAT, ret);

  return ret;
}