/** * _gst_caps_set_buffer_array: * @caps: a #GstCaps * @field: field in caps to set * @buf: header buffers * * Adds given buffers to an array of buffers set as the given @field * on the given @caps. List of buffer arguments must be NULL-terminated. * * Returns: input caps with a streamheader field added, or NULL if some error */ static GstCaps * _gst_caps_set_buffer_array (GstCaps * caps, const gchar * field, GstBuffer * buf, ...) { GstStructure *structure = NULL; va_list va; GValue array = { 0 }; GValue value = { 0 }; g_return_val_if_fail (caps != NULL, NULL); g_return_val_if_fail (gst_caps_is_fixed (caps), NULL); g_return_val_if_fail (field != NULL, NULL); caps = gst_caps_make_writable (caps); structure = gst_caps_get_structure (caps, 0); g_value_init (&array, GST_TYPE_ARRAY); va_start (va, buf); /* put buffers in a fixed list */ while (buf) { g_assert (gst_buffer_is_metadata_writable (buf)); /* mark buffer */ GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS); g_value_init (&value, GST_TYPE_BUFFER); buf = gst_buffer_copy (buf); GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS); gst_value_set_buffer (&value, buf); gst_buffer_unref (buf); gst_value_array_append_value (&array, &value); g_value_unset (&value); buf = va_arg (va, GstBuffer *); } gst_structure_set_value (structure, field, &array); g_value_unset (&array); return caps; }
static GstFlowReturn gst_identity_prepare_output_buffer (GstBaseTransform * trans, GstBuffer * in_buf, gint out_size, GstCaps * out_caps, GstBuffer ** out_buf) { GstIdentity *identity = GST_IDENTITY (trans); /* only bother if we may have to alter metadata */ if (identity->datarate > 0 || identity->single_segment) { if (gst_buffer_is_metadata_writable (in_buf)) *out_buf = gst_buffer_ref (in_buf); else { /* make even less writable */ gst_buffer_ref (in_buf); /* extra ref is dropped going through the official process */ *out_buf = gst_buffer_make_metadata_writable (in_buf); } } else *out_buf = gst_buffer_ref (in_buf); return GST_FLOW_OK; }
/** * gst_buffer_copy_metadata: * @dest: a destination #GstBuffer * @src: a source #GstBuffer * @flags: flags indicating what metadata fields should be copied. * * Copies the metadata from @src into @dest. The data, size and mallocdata * fields are not copied. * * @flags indicate which fields will be copied. Use #GST_BUFFER_COPY_ALL to copy * all the metadata fields. * * This function is typically called from a custom buffer copy function after * creating @dest and setting the data, size, mallocdata. * * Since: 0.10.13 */ void gst_buffer_copy_metadata (GstBuffer * dest, const GstBuffer * src, GstBufferCopyFlags flags) { g_return_if_fail (dest != NULL); g_return_if_fail (src != NULL); /* nothing to copy if the buffers are the same */ if (G_UNLIKELY (dest == src)) return; #if GST_VERSION_NANO == 1 /* we enable this extra debugging in git versions only for now */ g_return_if_fail (gst_buffer_is_metadata_writable (dest)); #endif GST_CAT_LOG (GST_CAT_BUFFER, "copy %p to %p", src, dest); if (flags & GST_BUFFER_COPY_FLAGS) { guint mask; /* copy relevant flags */ mask = GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS | GST_BUFFER_FLAG_DELTA_UNIT | GST_BUFFER_FLAG_DISCONT | GST_BUFFER_FLAG_GAP | GST_BUFFER_FLAG_MEDIA1 | GST_BUFFER_FLAG_MEDIA2 | GST_BUFFER_FLAG_MEDIA3; GST_MINI_OBJECT_FLAGS (dest) |= GST_MINI_OBJECT_FLAGS (src) & mask; } if (flags & GST_BUFFER_COPY_TIMESTAMPS) { GST_BUFFER_TIMESTAMP (dest) = GST_BUFFER_TIMESTAMP (src); GST_BUFFER_DURATION (dest) = GST_BUFFER_DURATION (src); GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET (src); GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_END (src); } if (flags & GST_BUFFER_COPY_CAPS) { gst_caps_replace (&GST_BUFFER_CAPS (dest), GST_BUFFER_CAPS (src)); } }
/* Output buffer preparation... if the buffer has no caps, and * our allowed output caps is fixed, then give the caps to the * buffer. * This ensures that outgoing buffers have caps if we can, so * that pipelines like: * gst-launch filesrc location=rawsamples.raw ! * audio/x-raw-int,width=16,depth=16,rate=48000,channels=2, * endianness=4321,signed='(boolean)'true ! alsasink * will work. */ static GstFlowReturn gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf) { GstFlowReturn ret = GST_FLOW_OK; if (GST_BUFFER_CAPS (input) != NULL) { /* Output buffer already has caps */ GST_LOG_OBJECT (trans, "Input buffer already has caps (implicitely fixed)"); /* FIXME : Move this behaviour to basetransform. The given caps are the ones * of the source pad, therefore our outgoing buffers should always have * those caps. */ gst_buffer_set_caps (input, caps); gst_buffer_ref (input); *buf = input; } else { /* Buffer has no caps. See if the output pad only supports fixed caps */ GstCaps *out_caps; out_caps = GST_PAD_CAPS (trans->srcpad); if (out_caps != NULL) { gst_caps_ref (out_caps); } else { out_caps = gst_pad_get_allowed_caps (trans->srcpad); g_return_val_if_fail (out_caps != NULL, GST_FLOW_ERROR); } out_caps = gst_caps_make_writable (out_caps); gst_caps_do_simplify (out_caps); if (gst_caps_is_fixed (out_caps) && !gst_caps_is_empty (out_caps)) { GST_DEBUG_OBJECT (trans, "Have fixed output caps %" GST_PTR_FORMAT " to apply to buffer with no caps", out_caps); if (gst_buffer_is_metadata_writable (input)) { gst_buffer_ref (input); *buf = input; } else { GST_DEBUG_OBJECT (trans, "Creating sub-buffer and setting caps"); *buf = gst_buffer_create_sub (input, 0, GST_BUFFER_SIZE (input)); } GST_BUFFER_CAPS (*buf) = out_caps; if (GST_PAD_CAPS (trans->srcpad) == NULL) gst_pad_set_caps (trans->srcpad, out_caps); } else { gchar *caps_str = gst_caps_to_string (out_caps); GST_DEBUG_OBJECT (trans, "Cannot choose caps. Have unfixed output caps %" GST_PTR_FORMAT, out_caps); gst_caps_unref (out_caps); ret = GST_FLOW_ERROR; GST_ELEMENT_ERROR (trans, STREAM, FORMAT, ("Filter caps do not completely specify the output format"), ("Output caps are unfixed: %s", caps_str)); g_free (caps_str); } } return ret; }