static gboolean gst_vdp_vpp_sink_setcaps (GstPad * pad, GstCaps * caps) { GstVdpVideoPostProcess *vpp = GST_VDP_VIDEO_POST_PROCESS (gst_pad_get_parent (pad)); GstStructure *structure; GstCaps *output_caps, *allowed_caps, *src_caps; gboolean res; /* extract interlaced flag */ structure = gst_caps_get_structure (caps, 0); gst_structure_get_boolean (structure, "interlaced", &vpp->interlaced); allowed_caps = gst_pad_get_allowed_caps (vpp->srcpad); structure = gst_caps_get_structure (allowed_caps, 0); output_caps = gst_vdp_video_to_output_caps (caps); src_caps = gst_caps_intersect (output_caps, allowed_caps); gst_caps_truncate (src_caps); if (gst_caps_is_empty (src_caps)) goto invalid_caps; GST_DEBUG ("output_caps: %" GST_PTR_FORMAT " allowed_caps: %" GST_PTR_FORMAT " src_caps: %" GST_PTR_FORMAT, output_caps, allowed_caps, src_caps); gst_caps_unref (output_caps); gst_caps_unref (allowed_caps); if (gst_vdp_vpp_is_interlaced (vpp)) { gint fps_n, fps_d; structure = gst_caps_get_structure (src_caps, 0); if (!gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)) { gst_caps_unref (src_caps); goto invalid_caps; } gst_fraction_double (&fps_n, &fps_d); gst_structure_set (structure, "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL); gst_structure_remove_field (structure, "interlaced"); vpp->field_duration = gst_util_uint64_scale (GST_SECOND, fps_d, fps_n); } res = gst_pad_set_caps (vpp->srcpad, src_caps); done: gst_object_unref (vpp); return res; invalid_caps: GST_ERROR_OBJECT (vpp, "invalid caps: %" GST_PTR_FORMAT, caps); res = FALSE; goto done; }
static gboolean gst_vdp_vpp_sink_setcaps (GstPad * pad, GstCaps * caps) { GstVdpVideoPostProcess *vpp = GST_VDP_VIDEO_POST_PROCESS (gst_pad_get_parent (pad)); GstStructure *structure; GstCaps *video_caps = NULL; gboolean res = FALSE; GstCaps *allowed_caps, *output_caps, *src_caps; /* check if the input is non native */ structure = gst_caps_get_structure (caps, 0); if (gst_structure_has_name (structure, "video/x-raw-yuv")) { if (!gst_structure_get_fourcc (structure, "format", &vpp->fourcc)) goto done; vpp->native_input = FALSE; video_caps = gst_vdp_yuv_to_video_caps (caps); if (!video_caps) goto done; if (!vpp->vpool) vpp->vpool = gst_vdp_video_buffer_pool_new (vpp->device); gst_vdp_buffer_pool_set_caps (vpp->vpool, video_caps); } else { vpp->native_input = TRUE; video_caps = gst_caps_ref (caps); if (vpp->vpool) { g_object_unref (vpp->vpool); vpp->vpool = NULL; } } structure = gst_caps_get_structure (video_caps, 0); if (!gst_structure_get_int (structure, "width", &vpp->width) || !gst_structure_get_int (structure, "height", &vpp->height) || !gst_structure_get_int (structure, "chroma-type", (gint *) & vpp->chroma_type)) goto done; /* get interlaced flag */ gst_structure_get_boolean (structure, "interlaced", &vpp->interlaced); /* extract par */ if (gst_structure_has_field_typed (structure, "pixel-aspect-ratio", GST_TYPE_FRACTION)) { gst_structure_get_fraction (structure, "pixel-aspect-ratio", &vpp->par_n, &vpp->par_d); vpp->got_par = TRUE; } else vpp->got_par = FALSE; allowed_caps = gst_pad_get_allowed_caps (vpp->srcpad); if (G_UNLIKELY (!allowed_caps)) goto null_allowed_caps; if (G_UNLIKELY (gst_caps_is_empty (allowed_caps))) goto empty_allowed_caps; GST_DEBUG ("allowed_caps: %" GST_PTR_FORMAT, allowed_caps); output_caps = gst_vdp_video_to_output_caps (video_caps); src_caps = gst_caps_intersect (output_caps, allowed_caps); gst_caps_unref (allowed_caps); gst_caps_unref (output_caps); if (gst_caps_is_empty (src_caps)) goto not_negotiated; gst_pad_fixate_caps (vpp->srcpad, src_caps); if (gst_vdp_vpp_is_interlaced (vpp)) { gint fps_n, fps_d; if (gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)) { gst_fraction_double (&fps_n, &fps_d); gst_caps_set_simple (src_caps, "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL); vpp->field_duration = gst_util_uint64_scale (GST_SECOND, fps_d, fps_n); } gst_caps_set_simple (src_caps, "interlaced", G_TYPE_BOOLEAN, FALSE, NULL); } GST_DEBUG ("src_caps: %" GST_PTR_FORMAT, src_caps); res = gst_pad_set_caps (vpp->srcpad, src_caps); gst_caps_unref (src_caps); done: gst_object_unref (vpp); if (video_caps) gst_caps_unref (video_caps); return res; null_allowed_caps: GST_ERROR_OBJECT (vpp, "Got null from gst_pad_get_allowed_caps"); goto done; empty_allowed_caps: GST_ERROR_OBJECT (vpp, "Got EMPTY caps from gst_pad_get_allowed_caps"); gst_caps_unref (allowed_caps); goto done; not_negotiated: gst_caps_unref (src_caps); GST_ERROR_OBJECT (vpp, "Couldn't find suitable output format"); goto done; }
static GstCaps * gst_deinterlace2_getcaps (GstPad * pad) { GstCaps *ret; GstDeinterlace2 *self = GST_DEINTERLACE2 (gst_pad_get_parent (pad)); GstPad *otherpad; gint len; const GstCaps *ourcaps; GstCaps *peercaps; GST_OBJECT_LOCK (self); otherpad = (pad == self->srcpad) ? self->sinkpad : self->srcpad; ourcaps = gst_pad_get_pad_template_caps (pad); peercaps = gst_pad_peer_get_caps (otherpad); if (peercaps) { ret = gst_caps_intersect (ourcaps, peercaps); gst_caps_unref (peercaps); } else { ret = gst_caps_copy (ourcaps); } GST_OBJECT_UNLOCK (self); if (self->fields == GST_DEINTERLACE2_ALL) { for (len = gst_caps_get_size (ret); len > 0; len--) { GstStructure *s = gst_caps_get_structure (ret, len - 1); const GValue *val; val = gst_structure_get_value (s, "framerate"); if (!val) continue; if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION) { gint n, d; n = gst_value_get_fraction_numerator (val); d = gst_value_get_fraction_denominator (val); if (!gst_fraction_double (&n, &d, pad != self->srcpad)) { goto error; } gst_structure_set (s, "framerate", GST_TYPE_FRACTION, n, d, NULL); } else if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION_RANGE) { const GValue *min, *max; GValue nrange = { 0, }, nmin = { 0,}, nmax = { 0,}; gint n, d; g_value_init (&nrange, GST_TYPE_FRACTION_RANGE); g_value_init (&nmin, GST_TYPE_FRACTION); g_value_init (&nmax, GST_TYPE_FRACTION); min = gst_value_get_fraction_range_min (val); max = gst_value_get_fraction_range_max (val); n = gst_value_get_fraction_numerator (min); d = gst_value_get_fraction_denominator (min); if (!gst_fraction_double (&n, &d, pad != self->srcpad)) { g_value_unset (&nrange); g_value_unset (&nmax); g_value_unset (&nmin); goto error; } gst_value_set_fraction (&nmin, n, d); n = gst_value_get_fraction_numerator (max); d = gst_value_get_fraction_denominator (max); if (!gst_fraction_double (&n, &d, pad != self->srcpad)) { g_value_unset (&nrange); g_value_unset (&nmax); g_value_unset (&nmin); goto error; } gst_value_set_fraction (&nmax, n, d); gst_value_set_fraction_range (&nrange, &nmin, &nmax); gst_structure_set_value (s, "framerate", &nrange); g_value_unset (&nmin); g_value_unset (&nmax); g_value_unset (&nrange); } else if (G_VALUE_TYPE (val) == GST_TYPE_LIST) { const GValue *lval; GValue nlist = { 0, }; GValue nval = { 0, }; gint i; g_value_init (&nlist, GST_TYPE_LIST); for (i = gst_value_list_get_size (val); i > 0; i--) { gint n, d; lval = gst_value_list_get_value (val, i); if (G_VALUE_TYPE (lval) != GST_TYPE_FRACTION) continue; n = gst_value_get_fraction_numerator (lval); d = gst_value_get_fraction_denominator (lval); /* Double/Half the framerate but if this fails simply * skip this value from the list */ if (!gst_fraction_double (&n, &d, pad != self->srcpad)) { continue; } g_value_init (&nval, GST_TYPE_FRACTION); gst_value_set_fraction (&nval, n, d); gst_value_list_append_value (&nlist, &nval); g_value_unset (&nval); } gst_structure_set_value (s, "framerate", &nlist); g_value_unset (&nlist); } } } GST_DEBUG_OBJECT (pad, "Returning caps %" GST_PTR_FORMAT, ret); return ret; error: GST_ERROR_OBJECT (pad, "Unable to transform peer caps"); gst_caps_unref (ret); return NULL; }
static gboolean gst_deinterlace2_setcaps (GstPad * pad, GstCaps * caps) { gboolean res = TRUE; GstDeinterlace2 *self = GST_DEINTERLACE2 (gst_pad_get_parent (pad)); GstPad *otherpad; GstStructure *structure; GstVideoFormat fmt; guint32 fourcc; GstCaps *othercaps; otherpad = (pad == self->srcpad) ? self->sinkpad : self->srcpad; structure = gst_caps_get_structure (caps, 0); res = gst_structure_get_int (structure, "width", &self->frame_width); res &= gst_structure_get_int (structure, "height", &self->frame_height); res &= gst_structure_get_fraction (structure, "framerate", &self->frame_rate_n, &self->frame_rate_d); res &= gst_structure_get_fourcc (structure, "format", &fourcc); /* TODO: get interlaced, field_layout, field_order */ if (!res) goto invalid_caps; if (self->fields == GST_DEINTERLACE2_ALL) { gint fps_n = self->frame_rate_n, fps_d = self->frame_rate_d; if (!gst_fraction_double (&fps_n, &fps_d, otherpad != self->srcpad)) goto invalid_caps; othercaps = gst_caps_copy (caps); gst_caps_set_simple (othercaps, "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL); } else { othercaps = gst_caps_ref (caps); } if (!gst_pad_set_caps (otherpad, othercaps)) goto caps_not_accepted; gst_caps_unref (othercaps); /* TODO: introduce self->field_stride */ self->field_height = self->frame_height / 2; fmt = gst_video_format_from_fourcc (fourcc); /* TODO: only true if fields are subbuffers of interlaced frames, change when the buffer-fields concept has landed */ self->field_stride = gst_video_format_get_row_stride (fmt, 0, self->frame_width) * 2; self->output_stride = gst_video_format_get_row_stride (fmt, 0, self->frame_width); /* in bytes */ self->line_length = gst_video_format_get_row_stride (fmt, 0, self->frame_width); self->frame_size = gst_video_format_get_size (fmt, self->frame_width, self->frame_height); if (self->fields == GST_DEINTERLACE2_ALL && otherpad == self->srcpad) self->field_duration = gst_util_uint64_scale (GST_SECOND, self->frame_rate_d, self->frame_rate_n); else self->field_duration = gst_util_uint64_scale (GST_SECOND, self->frame_rate_d, 2 * self->frame_rate_n); GST_DEBUG_OBJECT (self, "Set caps: %" GST_PTR_FORMAT, caps); done: gst_object_unref (self); return res; invalid_caps: res = FALSE; GST_ERROR_OBJECT (pad, "Invalid caps: %" GST_PTR_FORMAT, caps); goto done; caps_not_accepted: res = FALSE; GST_ERROR_OBJECT (pad, "Caps not accepted: %" GST_PTR_FORMAT, othercaps); gst_caps_unref (othercaps); goto done; }