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); }
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; }