static gboolean
gst_xviddec_setcaps (GstPad * pad, GstCaps * caps)
{
  GstXvidDec *dec = GST_XVIDDEC (GST_PAD_PARENT (pad));
  GstStructure *structure;
  GstCaps *allowed_caps;
  const GValue *val;

  GST_LOG_OBJECT (dec, "caps %" GST_PTR_FORMAT, caps);

  /* if there's something old around, remove it */
  if (dec->handle) {
    gst_xviddec_unset (dec);
  }

  structure = gst_caps_get_structure (caps, 0);
  gst_structure_get_int (structure, "width", &dec->width);
  gst_structure_get_int (structure, "height", &dec->height);

  /* perhaps some fps info */
  val = gst_structure_get_value (structure, "framerate");
  if ((val != NULL) && GST_VALUE_HOLDS_FRACTION (val)) {
    dec->fps_n = gst_value_get_fraction_numerator (val);
    dec->fps_d = gst_value_get_fraction_denominator (val);
  } else {
    dec->fps_n = -1;
    dec->fps_d = 1;
  }

  /* perhaps some par info */
  val = gst_structure_get_value (structure, "pixel-aspect-ratio");
  if (val != NULL && GST_VALUE_HOLDS_FRACTION (val)) {
    dec->par_n = gst_value_get_fraction_numerator (val);
    dec->par_d = gst_value_get_fraction_denominator (val);
  } else {
    dec->par_n = 1;
    dec->par_d = 1;
  }

  /* we try to find the preferred/accept csp */
  allowed_caps = gst_pad_get_allowed_caps (dec->srcpad);
  if (!allowed_caps) {
    GST_DEBUG_OBJECT (dec, "... but no peer, using template caps");
    /* need to copy because get_allowed_caps returns a ref,
       and get_pad_template_caps doesn't */
    allowed_caps = gst_caps_copy (gst_pad_get_pad_template_caps (dec->srcpad));
  }
  GST_LOG_OBJECT (dec, "allowed source caps %" GST_PTR_FORMAT, allowed_caps);

  /* pick the first one ... */
  structure = gst_caps_get_structure (allowed_caps, 0);
  val = gst_structure_get_value (structure, "format");
  if (val != NULL && G_VALUE_TYPE (val) == GST_TYPE_LIST) {
    GValue temp = { 0, };
    gst_value_init_and_copy (&temp, gst_value_list_get_value (val, 0));
    gst_structure_set_value (structure, "format", &temp);
    g_value_unset (&temp);
  }

  /* ... and use its info to get the csp */
  dec->csp = gst_xvid_structure_to_csp (structure);
  if (dec->csp == -1) {
    GST_WARNING_OBJECT (dec, "failed to decide on colorspace, using I420");
    dec->csp = XVID_CSP_I420;
  }

  dec->outbuf_size =
      gst_xvid_image_get_size (dec->csp, dec->width, dec->height);

  GST_LOG_OBJECT (dec, "csp=%d, outbuf_size=%d", dec->csp, dec->outbuf_size);

  gst_caps_unref (allowed_caps);

  /* now set up xvid ... */
  if (!gst_xviddec_setup (dec)) {
    GST_ELEMENT_ERROR (GST_ELEMENT (dec), LIBRARY, INIT, (NULL), (NULL));
    return FALSE;
  }

  return gst_xviddec_negotiate (dec, NULL);
}
Beispiel #2
0
static gboolean
gst_xvidenc_setcaps (GstPad * pad, GstCaps * vscaps)
{
  GstXvidEnc *xvidenc;
  GstStructure *structure;
  gint w, h;
  const GValue *fps, *par;
  gint xvid_cs = -1;

  xvidenc = GST_XVIDENC (GST_PAD_PARENT (pad));

  /* if there's something old around, remove it */
  if (xvidenc->handle) {
    gst_xvidenc_flush_buffers (xvidenc, TRUE);
    xvid_encore (xvidenc->handle, XVID_ENC_DESTROY, NULL, NULL);
    xvidenc->handle = NULL;
  }

  structure = gst_caps_get_structure (vscaps, 0);

  if (!gst_structure_get_int (structure, "width", &w) ||
      !gst_structure_get_int (structure, "height", &h)) {
    return FALSE;
  }

  fps = gst_structure_get_value (structure, "framerate");
  if (fps == NULL || !GST_VALUE_HOLDS_FRACTION (fps)) {
    GST_WARNING_OBJECT (pad, "no framerate specified, or not a GstFraction");
    return FALSE;
  }

  /* optional par info */
  par = gst_structure_get_value (structure, "pixel-aspect-ratio");

  xvid_cs = gst_xvid_structure_to_csp (structure);
  if (xvid_cs == -1) {
    gchar *sstr;

    sstr = gst_structure_to_string (structure);
    GST_DEBUG_OBJECT (xvidenc, "Did not find xvid colourspace for caps %s",
        sstr);
    g_free (sstr);
    return FALSE;
  }

  xvidenc->csp = xvid_cs;
  xvidenc->width = w;
  xvidenc->height = h;
  xvidenc->fbase = gst_value_get_fraction_numerator (fps);
  xvidenc->fincr = gst_value_get_fraction_denominator (fps);
  if ((par != NULL) && GST_VALUE_HOLDS_FRACTION (par)) {
    xvidenc->par_width = gst_value_get_fraction_numerator (par);
    xvidenc->par_height = gst_value_get_fraction_denominator (par);
  } else {
    xvidenc->par_width = 1;
    xvidenc->par_height = 1;
  }

  /* wipe xframe cache given possible change caps properties */
  g_free (xvidenc->xframe_cache);
  xvidenc->xframe_cache = NULL;

  if (gst_xvidenc_setup (xvidenc)) {
    gboolean ret = FALSE;
    GstCaps *new_caps = NULL, *allowed_caps;

    /* please downstream with preferred caps */
    allowed_caps = gst_pad_get_allowed_caps (xvidenc->srcpad);
    GST_DEBUG_OBJECT (xvidenc, "allowed caps: %" GST_PTR_FORMAT, allowed_caps);

    if (allowed_caps && !gst_caps_is_empty (allowed_caps)) {
      new_caps = gst_caps_copy_nth (allowed_caps, 0);
    } else {
      new_caps = gst_caps_new_simple ("video/x-xvid", NULL);
    }
    if (allowed_caps)
      gst_caps_unref (allowed_caps);

    gst_caps_set_simple (new_caps,
        "width", G_TYPE_INT, w, "height", G_TYPE_INT, h,
        "framerate", GST_TYPE_FRACTION, xvidenc->fbase, xvidenc->fincr,
        "pixel-aspect-ratio", GST_TYPE_FRACTION,
        xvidenc->par_width, xvidenc->par_height, NULL);
    /* just to be sure */
    gst_pad_fixate_caps (xvidenc->srcpad, new_caps);

    if (xvidenc->used_profile != 0) {
      switch (xvidenc->used_profile) {
        case XVID_PROFILE_S_L0:
          gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, "simple",
              "level", G_TYPE_STRING, "0", NULL);
          break;
        case XVID_PROFILE_S_L1:
          gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, "simple",
              "level", G_TYPE_STRING, "1", NULL);
          break;
        case XVID_PROFILE_S_L2:
          gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, "simple",
              "level", G_TYPE_STRING, "2", NULL);
          break;
        case XVID_PROFILE_S_L3:
          gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, "simple",
              "level", G_TYPE_STRING, "3", NULL);
          break;
       /* case XVID_PROFILE_S_L4a:
          gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, "simple",
              "level", G_TYPE_STRING, "4a", NULL);
          break;
        case XVID_PROFILE_S_L5:
          gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, "simple",
              "level", G_TYPE_STRING, "5", NULL);
          break;
        case XVID_PROFILE_S_L6:
          gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, "simple",
              "level", G_TYPE_STRING, "6", NULL);
          break;*/
        case XVID_PROFILE_ARTS_L1:
          gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING,
              "advanced-real-time-simple", "level", G_TYPE_STRING, "1", NULL);
          break;
        case XVID_PROFILE_ARTS_L2:
          gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING,
              "advanced-real-time-simple", "level", G_TYPE_STRING, "2", NULL);
          break;
        case XVID_PROFILE_ARTS_L3:
          gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING,
              "advanced-real-time-simple", "level", G_TYPE_STRING, "3", NULL);
          break;
        case XVID_PROFILE_ARTS_L4:
          gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING,
              "advanced-real-time-simple", "level", G_TYPE_STRING, "4", NULL);
          break;
        case XVID_PROFILE_AS_L0:
          gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING,
              "advanced-simple", "level", G_TYPE_STRING, "0", NULL);
          break;
        case XVID_PROFILE_AS_L1:
          gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING,
              "advanced-simple", "level", G_TYPE_STRING, "1", NULL);
          break;
        case XVID_PROFILE_AS_L2:
          gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING,
              "advanced-simple", "level", G_TYPE_STRING, "2", NULL);
          break;
        case XVID_PROFILE_AS_L3:
          gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING,
              "advanced-simple", "level", G_TYPE_STRING, "3", NULL);
          break;
        case XVID_PROFILE_AS_L4:
          gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING,
              "advanced-simple", "level", G_TYPE_STRING, "4", NULL);
          break;
        default:
          g_assert_not_reached ();
          break;
      }
    }

    /* src pad should accept anyway */
    ret = gst_pad_set_caps (xvidenc->srcpad, new_caps);
    gst_caps_unref (new_caps);

    if (!ret && xvidenc->handle) {
      xvid_encore (xvidenc->handle, XVID_ENC_DESTROY, NULL, NULL);
      xvidenc->handle = NULL;
    }
    return ret;

  } else                        /* setup did not work out */
    return FALSE;
}