static GstFlowReturn gst_vdp_mpeg_dec_alloc_buffer (GstVdpMpegDec * mpeg_dec, GstBuffer ** outbuf) { GstFlowReturn ret; ret = gst_pad_alloc_buffer_and_set_caps (mpeg_dec->src, 0, 0, GST_PAD_CAPS (mpeg_dec->src), outbuf); if (ret != GST_FLOW_OK) return ret; if (!mpeg_dec->device) { GstVdpDevice *device; VdpStatus status; device = mpeg_dec->device = g_object_ref (GST_VDP_VIDEO_BUFFER (*outbuf)->device); status = device->vdp_decoder_create (device->device, mpeg_dec->profile, mpeg_dec->width, mpeg_dec->height, 2, &mpeg_dec->decoder); if (status != VDP_STATUS_OK) { GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, ("Could not create vdpau decoder"), ("Error returned from vdpau was: %s", device->vdp_get_error_string (status))); ret = GST_FLOW_ERROR; } } return ret; }
static boolean gst_jpegenc_flush_destination (j_compress_ptr cinfo) { GstBuffer *overflow_buffer; guint32 old_buffer_size; GstJpegEnc *jpegenc = (GstJpegEnc *) (cinfo->client_data); GST_DEBUG_OBJECT (jpegenc, "gst_jpegenc_chain: flush_destination: buffer too small"); /* Our output buffer wasn't big enough. * Make a new buffer that's twice the size, */ old_buffer_size = GST_BUFFER_SIZE (jpegenc->output_buffer); gst_pad_alloc_buffer_and_set_caps (jpegenc->srcpad, GST_BUFFER_OFFSET_NONE, old_buffer_size * 2, GST_PAD_CAPS (jpegenc->srcpad), &overflow_buffer); memcpy (GST_BUFFER_DATA (overflow_buffer), GST_BUFFER_DATA (jpegenc->output_buffer), old_buffer_size); gst_buffer_copy_metadata (overflow_buffer, jpegenc->output_buffer, GST_BUFFER_COPY_TIMESTAMPS); /* drop it into place, */ gst_buffer_unref (jpegenc->output_buffer); jpegenc->output_buffer = overflow_buffer; /* and last, update libjpeg on where to work. */ jpegenc->jdest.next_output_byte = GST_BUFFER_DATA (jpegenc->output_buffer) + old_buffer_size; jpegenc->jdest.free_in_buffer = GST_BUFFER_SIZE (jpegenc->output_buffer) - old_buffer_size; return TRUE; }
static GstFlowReturn get_buffer (GstMonoscope * monoscope, GstBuffer ** outbuf) { GstFlowReturn ret; if (GST_PAD_CAPS (monoscope->srcpad) == NULL) { if (!gst_monoscope_src_negotiate (monoscope)) return GST_FLOW_NOT_NEGOTIATED; } GST_LOG_OBJECT (monoscope, "allocating output buffer of size %d with caps %" GST_PTR_FORMAT, monoscope->outsize, GST_PAD_CAPS (monoscope->srcpad)); ret = gst_pad_alloc_buffer_and_set_caps (monoscope->srcpad, GST_BUFFER_OFFSET_NONE, monoscope->outsize, GST_PAD_CAPS (monoscope->srcpad), outbuf); if (ret != GST_FLOW_OK) return ret; if (*outbuf == NULL) return GST_FLOW_ERROR; return GST_FLOW_OK; }
static void user_info_callback (png_structp png_ptr, png_infop info) { GstPngDec *pngdec = NULL; GstFlowReturn ret = GST_FLOW_OK; size_t buffer_size; GstBuffer *buffer = NULL; pngdec = GST_PNGDEC (png_ptr->io_ptr); GST_LOG ("info ready"); /* Generate the caps and configure */ ret = gst_pngdec_caps_create_and_set (pngdec); if (ret != GST_FLOW_OK) { goto beach; } /* Allocate output buffer */ pngdec->rowbytes = png_get_rowbytes (pngdec->png, pngdec->info); buffer_size = pngdec->height * GST_ROUND_UP_4 (pngdec->rowbytes); ret = gst_pad_alloc_buffer_and_set_caps (pngdec->srcpad, GST_BUFFER_OFFSET_NONE, buffer_size, GST_PAD_CAPS (pngdec->srcpad), &buffer); if (ret != GST_FLOW_OK) { goto beach; } pngdec->buffer_out = buffer; beach: pngdec->ret = ret; }
/* allocate and output buffer, if no format was negotiated, this * function will negotiate one. After calling this function, a * reverse negotiation could have happened. */ static GstFlowReturn get_buffer (GstVisual * visual, GstBuffer ** outbuf) { GstFlowReturn ret; /* we don't know an output format yet, pick one */ if (GST_PAD_CAPS (visual->srcpad) == NULL) { if (!gst_vis_src_negotiate (visual)) return GST_FLOW_NOT_NEGOTIATED; } GST_DEBUG_OBJECT (visual, "allocating output buffer with caps %" GST_PTR_FORMAT, GST_PAD_CAPS (visual->srcpad)); /* now allocate a buffer with the last negotiated format. * Downstream could renegotiate a new format, which will trigger * our setcaps function on the source pad. */ ret = gst_pad_alloc_buffer_and_set_caps (visual->srcpad, GST_BUFFER_OFFSET_NONE, visual->outsize, GST_PAD_CAPS (visual->srcpad), outbuf); /* no buffer allocated, we don't care why. */ if (ret != GST_FLOW_OK) return ret; return GST_FLOW_OK; }
static GstFlowReturn pad_chain(GstPad *pad, GstBuffer *buf) { GstDspDummy *self; GstFlowReturn ret; GstBuffer *out_buf; self = GST_DSP_DUMMY(GST_OBJECT_PARENT(pad)); ret = gst_pad_alloc_buffer_and_set_caps(self->srcpad, GST_BUFFER_OFFSET_NONE, GST_BUFFER_SIZE(buf), GST_BUFFER_CAPS(buf), &out_buf); if (G_UNLIKELY(ret != GST_FLOW_OK)) { GST_ERROR_OBJECT(self, "couldn't allocate buffer"); ret = GST_FLOW_ERROR; goto leave; } /* map dsp to gpp address */ map_buffer(self, buf, self->in_buffer); map_buffer(self, out_buf, self->out_buffer); configure_dsp_node(self->dsp_handle, self->node, self->in_buffer, self->out_buffer); if (self->in_buffer->need_copy) { memcpy(self->in_buffer->data, GST_BUFFER_DATA(buf), GST_BUFFER_SIZE(buf)); self->in_buffer->need_copy = false; } { dsp_msg_t msg; dmm_buffer_clean(self->in_buffer, self->in_buffer->size); msg.cmd = 1; msg.arg_1 = self->in_buffer->size; dsp_node_put_message(self->dsp_handle, self->node, &msg, -1); dsp_node_get_message(self->dsp_handle, self->node, &msg, -1); dmm_buffer_invalidate(self->out_buffer, self->out_buffer->size); } if (self->out_buffer->need_copy) { memcpy(GST_BUFFER_DATA(out_buf), self->out_buffer->data, GST_BUFFER_SIZE(out_buf)); self->out_buffer->need_copy = false; } GST_BUFFER_TIMESTAMP(out_buf) = GST_BUFFER_TIMESTAMP(buf); ret = gst_pad_push(self->srcpad, out_buf); leave: gst_buffer_unref(buf); return ret; }
/* Allocate buffer and copy image data into Y444 format */ static GstFlowReturn theora_handle_image (GstTheoraDec * dec, th_ycbcr_buffer buf, GstBuffer ** out) { gint width, height, stride; GstFlowReturn result; int i, plane; GstVideoFormat format; guint8 *dest, *src; switch (dec->info.pixel_fmt) { case TH_PF_444: format = GST_VIDEO_FORMAT_Y444; break; case TH_PF_420: format = GST_VIDEO_FORMAT_I420; break; case TH_PF_422: format = GST_VIDEO_FORMAT_Y42B; break; default: g_assert_not_reached (); } result = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE, gst_video_format_get_size (format, dec->width, dec->height), GST_PAD_CAPS (dec->srcpad), out); if (G_UNLIKELY (result != GST_FLOW_OK)) { GST_DEBUG_OBJECT (dec, "could not get buffer, reason: %s", gst_flow_get_name (result)); return result; } for (plane = 0; plane < 3; plane++) { width = gst_video_format_get_component_width (format, plane, dec->width); height = gst_video_format_get_component_height (format, plane, dec->height); stride = gst_video_format_get_row_stride (format, plane, dec->width); dest = GST_BUFFER_DATA (*out) + gst_video_format_get_component_offset (format, plane, dec->width, dec->height); src = buf[plane].data; src += ((height == dec->height) ? dec->offset_y : dec->offset_y / 2) * buf[plane].stride; src += (width == dec->width) ? dec->offset_x : dec->offset_x / 2; for (i = 0; i < height; i++) { memcpy (dest, src, width); dest += stride; src += buf[plane].stride; } } return GST_FLOW_OK; }
static GstFlowReturn gst_a52dec_push (GstA52Dec * a52dec, GstPad * srcpad, int flags, sample_t * samples, GstClockTime timestamp) { GstBuffer *buf; int chans, n, c; GstFlowReturn result; flags &= (A52_CHANNEL_MASK | A52_LFE); chans = gst_a52dec_channels (flags, NULL); if (!chans) { GST_ELEMENT_ERROR (GST_ELEMENT (a52dec), STREAM, DECODE, (NULL), ("invalid channel flags: %d", flags)); return GST_FLOW_ERROR; } result = gst_pad_alloc_buffer_and_set_caps (srcpad, 0, 256 * chans * (SAMPLE_WIDTH / 8), GST_PAD_CAPS (srcpad), &buf); if (result != GST_FLOW_OK) return result; for (n = 0; n < 256; n++) { for (c = 0; c < chans; c++) { ((sample_t *) GST_BUFFER_DATA (buf))[n * chans + c] = samples[c * 256 + n]; } } GST_BUFFER_TIMESTAMP (buf) = timestamp; GST_BUFFER_DURATION (buf) = 256 * GST_SECOND / a52dec->sample_rate; result = GST_FLOW_OK; if ((buf = gst_audio_buffer_clip (buf, &a52dec->segment, a52dec->sample_rate, (SAMPLE_WIDTH / 8) * chans))) { /* set discont when needed */ if (a52dec->discont) { GST_LOG_OBJECT (a52dec, "marking DISCONT"); GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); a52dec->discont = FALSE; } if (a52dec->segment.rate > 0.0) { GST_DEBUG_OBJECT (a52dec, "Pushing buffer with ts %" GST_TIME_FORMAT " duration %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); result = gst_pad_push (srcpad, buf); } else { /* reverse playback, queue frame till later when we get a discont. */ GST_DEBUG_OBJECT (a52dec, "queued frame"); a52dec->queued = g_list_prepend (a52dec->queued, buf); } } return result; }
static GstFlowReturn sbc_enc_chain(GstPad *pad, GstBuffer *buffer) { GstSbcEnc *enc = GST_SBC_ENC(gst_pad_get_parent(pad)); GstAdapter *adapter = enc->adapter; GstFlowReturn res = GST_FLOW_OK; gst_adapter_push(adapter, buffer); while (gst_adapter_available(adapter) >= enc->codesize && res == GST_FLOW_OK) { GstBuffer *output; GstCaps *caps; const guint8 *data; gint consumed; caps = GST_PAD_CAPS(enc->srcpad); res = gst_pad_alloc_buffer_and_set_caps(enc->srcpad, GST_BUFFER_OFFSET_NONE, enc->frame_length, caps, &output); if (res != GST_FLOW_OK) goto done; data = gst_adapter_peek(adapter, enc->codesize); consumed = sbc_encode(&enc->sbc, (gpointer) data, enc->codesize, GST_BUFFER_DATA(output), GST_BUFFER_SIZE(output), NULL); if (consumed <= 0) { GST_DEBUG_OBJECT(enc, "comsumed < 0, codesize: %d", enc->codesize); break; } gst_adapter_flush(adapter, consumed); GST_BUFFER_TIMESTAMP(output) = GST_BUFFER_TIMESTAMP(buffer); /* we have only 1 frame */ GST_BUFFER_DURATION(output) = enc->frame_duration; res = gst_pad_push(enc->srcpad, output); if (res != GST_FLOW_OK) goto done; } done: gst_object_unref(enc); return res; }
/** GstXineInput ***********************************************************/ enum { ARG_0, ARG_LOCATION }; GST_BOILERPLATE (GstXineInput, gst_xine_input, GstXine, GST_TYPE_XINE); static void gst_xine_input_dispose (GObject * object); static void gst_xine_input_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_xine_input_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static GstStateChangeReturn gst_xine_input_change_state (GstElement * element, GstStateChange transition); static void gst_xine_input_base_init (gpointer g_class) { } static void gst_xine_input_class_init (GstXineInputClass * klass) { GstElementClass *element = GST_ELEMENT_CLASS (klass); GObjectClass *object = G_OBJECT_CLASS (klass); element->change_state = gst_xine_input_change_state; object->set_property = gst_xine_input_set_property; object->get_property = gst_xine_input_get_property; object->dispose = gst_xine_input_dispose; g_object_class_install_property (object, ARG_LOCATION, g_param_spec_string ("location", "location", "location", NULL, G_PARAM_READWRITE)); } static void gst_xine_input_init (GstXineInput * xine, GstXineInputClass * g_class) { } static void gst_xine_input_dispose (GObject * object) { GstXineInput *xine = GST_XINE_INPUT (object); g_free (xine->location); xine->location = NULL; GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); } static void gst_xine_input_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstXineInput *xine = GST_XINE_INPUT (object); switch (prop_id) { case ARG_LOCATION: if (gst_element_get_state (GST_ELEMENT (xine)) != GST_STATE_NULL) return; if (xine->location) g_free (xine->location); xine->location = g_strdup (g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); return; } } static void gst_xine_input_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstXineInput *xine = GST_XINE_INPUT (object); switch (prop_id) { case ARG_LOCATION: g_value_set_string (value, xine->location); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); return; } } #define BUFFER_SIZE 4096 /* FIXME: what size? */ static GstData * gst_xine_input_get (GstPad * pad) { GstXineInput *xine = GST_XINE_INPUT (gst_object_get_parent (GST_OBJECT (pad))); GstBuffer *buf; gint real_size, position; /* FIXME: how does xine figure out EOS? */ position = xine->input->get_current_pos (xine->input); if (position > 0 && position == xine->input->get_length (xine->input)) { gst_element_set_eos (GST_ELEMENT (xine)); return GST_DATA (gst_event_new (GST_EVENT_EOS)); } buf = gst_pad_alloc_buffer_and_set_caps (xine->srcpad, GST_BUFFER_OFFSET_NONE, xine->blocksize); GST_BUFFER_OFFSET (buf) = position; real_size = xine->input->read (xine->input, GST_BUFFER_DATA (buf), GST_BUFFER_MAXSIZE (buf)); GST_BUFFER_SIZE (buf) = real_size; if (real_size < 0) { GST_ELEMENT_ERROR (xine, RESOURCE, READ, (NULL), ("error %d reading data", real_size)); gst_data_unref (GST_DATA (buf)); return NULL; } else if (real_size == 0) { buf_element_t *element; if (xine->input->get_capabilities (xine->input) & INPUT_CAP_BLOCK) element = xine->input->read_block (xine->input, gst_xine_get_stream (GST_XINE (xine))->audio_fifo, xine->blocksize); if (element == NULL) { /* FIXME: is this EOS? */ gst_element_set_eos (GST_ELEMENT (xine)); return GST_DATA (gst_event_new (GST_EVENT_EOS)); } else { GST_BUFFER_SIZE (buf) = element->size; /* FIXME: put buf_element_t data in buffer */ memcpy (GST_BUFFER_DATA (buf), element->mem, element->size); element->free_buffer (element); } } GST_BUFFER_OFFSET_END (buf) = xine->input->get_current_pos (xine->input); return GST_DATA (buf); }
/** * overrides the default buffer allocation for output port to allow * pad_alloc'ing from the srcpad */ static GstBuffer * buffer_alloc (GOmxPort *port, gint len) { GstOmxBaseSrc *self = port->core->object; GstBaseSrc *gst_base = GST_BASE_SRC (self); GstBuffer *buf; GstFlowReturn ret; check_settings (self->out_port, gst_base->srcpad); ret = gst_pad_alloc_buffer_and_set_caps ( gst_base->srcpad, GST_BUFFER_OFFSET_NONE, len, GST_PAD_CAPS (gst_base->srcpad), &buf); if (ret == GST_FLOW_OK) return buf; return NULL; }
static void live_switch_push (int rate, GstCaps * caps) { GstBuffer *inbuffer; GstCaps *desired; GList *l; desired = gst_caps_copy (caps); gst_caps_set_simple (desired, "rate", G_TYPE_INT, rate, NULL); gst_pad_set_caps (mysrcpad, desired); fail_unless (gst_pad_alloc_buffer_and_set_caps (mysrcpad, GST_BUFFER_OFFSET_NONE, rate * 4, desired, &inbuffer) == GST_FLOW_OK); /* When the basetransform hits the non-configured case it always * returns a buffer with exactly the same caps as we requested so the actual * renegotiation (if needed) will be done in the _chain*/ fail_unless (inbuffer != NULL); GST_DEBUG ("desired: %" GST_PTR_FORMAT ".... got: %" GST_PTR_FORMAT, desired, GST_BUFFER_CAPS (inbuffer)); fail_unless (gst_caps_is_equal (desired, GST_BUFFER_CAPS (inbuffer))); memset (GST_BUFFER_DATA (inbuffer), 0, GST_BUFFER_SIZE (inbuffer)); GST_BUFFER_DURATION (inbuffer) = GST_SECOND; GST_BUFFER_TIMESTAMP (inbuffer) = 0; GST_BUFFER_OFFSET (inbuffer) = 0; /* pushing gives away my reference ... */ fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); /* ... but it ends up being collected on the global buffer list */ fail_unless_equals_int (g_list_length (buffers), 1); for (l = buffers; l; l = l->next) { GstBuffer *buffer = GST_BUFFER (l->data); gst_buffer_unref (buffer); } g_list_free (buffers); buffers = NULL; gst_caps_unref (desired); }
/** * overrides the default buffer allocation for output port to allow * pad_alloc'ing from the srcpad */ static GstBuffer * buffer_alloc (GOmxPort *port, gint len) { GstOmxBaseFilter2 *self = port->core->object; GstBuffer *buf; GstFlowReturn ret; int i; for (i = 0; i < NUM_OUTPUTS; i++) if (port == self->out_port[i]) break; if (i >= NUM_OUTPUTS) return NULL; #if 1 /** @todo remove this check */ if (G_LIKELY (self->in_port->enabled)) { GstCaps *caps = NULL; caps = gst_pad_get_negotiated_caps (self->srcpad[i]); if (!caps) { /** @todo We shouldn't be doing this. */ GOmxCore *gomx = self->gomx; GST_WARNING_OBJECT (self, "faking settings changed notification"); if (gomx->settings_changed_cb) gomx->settings_changed_cb (gomx); } else { GST_LOG_OBJECT (self, "caps already fixed: %" GST_PTR_FORMAT, caps); gst_caps_unref (caps); } } #endif ret = gst_pad_alloc_buffer_and_set_caps ( self->srcpad[i], GST_BUFFER_OFFSET_NONE, len, GST_PAD_CAPS (self->srcpad[i]), &buf); if (ret == GST_FLOW_OK) return buf; return NULL; }
static GstFlowReturn gst_vdp_vpp_alloc_output_buffer (GstVdpVideoPostProcess * vpp, GstCaps * caps, GstVdpOutputBuffer ** outbuf) { GstFlowReturn ret; ret = gst_pad_alloc_buffer_and_set_caps (vpp->srcpad, 0, 0, caps, (GstBuffer **) outbuf); if (ret != GST_FLOW_OK) return ret; if (!vpp->device) { ret = gst_vdp_vpp_create_mixer (vpp, (*outbuf)->device); } if (ret != GST_FLOW_OK) gst_buffer_unref (GST_BUFFER (*outbuf)); return ret; }
static GstFlowReturn gst_caps_debug_bufferalloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf) { GstCapsDebug *capsdebug; gchar *s; gchar *t; GstFlowReturn ret; GstPad *otherpad; gboolean newcaps; capsdebug = GST_CAPS_DEBUG (gst_pad_get_parent (pad)); otherpad = (pad == capsdebug->srcpad) ? capsdebug->sinkpad : capsdebug->srcpad; newcaps = (caps != GST_PAD_CAPS (pad)); if (newcaps) { s = gst_caps_to_string (caps); GST_INFO ("%s called bufferalloc with new caps, offset=%" G_GUINT64_FORMAT " size=%d caps=%s", THISPAD, offset, size, s); g_free (s); } ret = gst_pad_alloc_buffer_and_set_caps (otherpad, offset, size, caps, buf); if (newcaps) { GST_INFO ("%s returned %s", OTHERPAD, gst_flow_get_name (ret)); } if (caps != GST_BUFFER_CAPS (*buf)) { s = gst_caps_to_string (caps); t = gst_caps_to_string (GST_BUFFER_CAPS (*buf)); GST_INFO ("%s returned from bufferalloc with different caps, requested=%s returned=%s", OTHERPAD, s, t); g_free (s); g_free (t); } gst_object_unref (capsdebug); return ret; }
static int get_buffer(AVCodecContext *avctx, AVFrame *pic) { GstBuffer *out_buf; GstFlowReturn ret; struct obj *self = avctx->opaque; int width = avctx->width; int height = avctx->height; avcodec_align_dimensions(avctx, &width, &height); pic->linesize[0] = width; pic->linesize[1] = width / 2; pic->linesize[2] = width / 2; if (avctx->width == width && avctx->height == height) { ret = gst_pad_alloc_buffer_and_set_caps(self->srcpad, 0, width * height * 3 / 2, self->srcpad->caps, &out_buf); if (ret != GST_FLOW_OK) return 1; gst_buffer_ref(out_buf); pic->opaque = out_buf; pic->data[0] = out_buf->data; pic->data[1] = pic->data[0] + pic->linesize[0] * height; pic->data[2] = pic->data[1] + pic->linesize[1] * height / 2; } else { ret = av_image_alloc(pic->base, pic->linesize, width, height, avctx->pix_fmt, 1); if (ret < 0) return ret; for (unsigned i = 0; i < 3; i++) pic->data[i] = pic->base[i]; } pic->type = FF_BUFFER_TYPE_USER; if (avctx->pkt) pic->pkt_pts = avctx->pkt->pts; else pic->pkt_pts = AV_NOPTS_VALUE; return 0; }
static GstFlowReturn gst_vdp_output_src_pad_create_buffer (GstVdpOutputSrcPad * vdp_pad, GstVdpOutputBuffer ** output_buf, GError ** error) { GstFlowReturn ret; GstBuffer *neg_buf; /* negotiate */ ret = gst_pad_alloc_buffer_and_set_caps (GST_PAD_CAST (vdp_pad), GST_BUFFER_OFFSET_NONE, 0, GST_PAD_CAPS (vdp_pad), &neg_buf); if (ret == GST_FLOW_OK) gst_buffer_unref (neg_buf); *output_buf = (GstVdpOutputBuffer *) gst_vdp_buffer_pool_get_buffer (vdp_pad->bpool, error); if (!*output_buf) return GST_FLOW_ERROR; return GST_FLOW_OK; }
static void gst_hermes_colorspace_chain (GstPad * pad, GstData * _data) { GstBuffer *buf = GST_BUFFER (_data); GstHermesColorspace *space; GstBuffer *outbuf = NULL; g_return_if_fail (pad != NULL); g_return_if_fail (GST_IS_PAD (pad)); g_return_if_fail (buf != NULL); space = GST_HERMES_COLORSPACE (gst_pad_get_parent (pad)); g_return_if_fail (space != NULL); g_return_if_fail (GST_IS_COLORSPACE (space)); if (space->passthru) { gst_pad_push (space->srcpad, _data); return; } if (GST_BUFFER_SIZE (buf) < space->sink_size) { g_critical ("input size is smaller than expected"); } outbuf = gst_pad_alloc_buffer_and_set_caps (space->srcpad, GST_BUFFER_OFFSET_NONE, space->src_size); Hermes_ConverterCopy (space->h_handle, GST_BUFFER_DATA (buf), 0, 0, space->width, space->height, space->sink_stride, GST_BUFFER_DATA (outbuf), 0, 0, space->width, space->height, space->src_stride); GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf); GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf); gst_buffer_unref (buf); gst_pad_push (space->srcpad, GST_DATA (outbuf)); }
static GstFlowReturn gst_teletextdec_export_rgba_page (GstTeletextDec * teletext, vbi_page * page, GstBuffer ** buf) { guint size; GstCaps *caps, *out_caps; GstFlowReturn ret; gint width, height; GstPadTemplate *templ; /* one character occupies 12 x 10 pixels */ width = page->columns * 12; height = page->rows * 10; caps = gst_caps_new_simple ("video/x-raw-rgb", "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, teletext->rate_numerator, teletext->rate_denominator, NULL); templ = gst_static_pad_template_get (&src_template); out_caps = gst_caps_intersect (caps, gst_pad_template_get_caps (templ)); gst_caps_unref (caps); gst_object_unref (templ); size = (guint) width *(guint) height *sizeof (vbi_rgba); ret = gst_pad_alloc_buffer_and_set_caps (teletext->srcpad, GST_BUFFER_OFFSET_NONE, size, out_caps, &(*buf)); if (ret == GST_FLOW_OK) { GST_DEBUG_OBJECT (teletext, "Creating image with %d rows and %d cols", page->rows, page->columns); vbi_draw_vt_page (page, VBI_PIXFMT_RGBA32_LE, (vbi_rgba *) GST_BUFFER_DATA (*buf), FALSE, TRUE); } gst_caps_unref (out_caps); return ret; }
static void live_switch_push (int rate, GstCaps * caps) { GstBuffer *inbuffer; GstCaps *desired; GList *l; desired = gst_caps_copy (caps); gst_caps_set_simple (desired, "rate", G_TYPE_INT, rate, NULL); gst_pad_set_caps (mysrcpad, desired); #if 0 fail_unless (gst_pad_alloc_buffer_and_set_caps (mysrcpad, GST_BUFFER_OFFSET_NONE, rate * 4, desired, &inbuffer) == GST_FLOW_OK); #endif inbuffer = gst_buffer_new_and_alloc (rate * 4); gst_buffer_memset (inbuffer, 0, 0, rate * 4); GST_BUFFER_DURATION (inbuffer) = GST_SECOND; GST_BUFFER_TIMESTAMP (inbuffer) = 0; GST_BUFFER_OFFSET (inbuffer) = 0; /* pushing gives away my reference ... */ fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); /* ... but it ends up being collected on the global buffer list */ fail_unless_equals_int (g_list_length (buffers), 1); for (l = buffers; l; l = l->next) { GstBuffer *buffer = GST_BUFFER (l->data); gst_buffer_unref (buffer); } g_list_free (buffers); buffers = NULL; gst_caps_unref (desired); }
static GstFlowReturn get_buffer (GstGoom * goom, GstBuffer ** outbuf) { GstFlowReturn ret; if (GST_PAD_CAPS (goom->srcpad) == NULL) { if (!gst_goom_src_negotiate (goom)) return GST_FLOW_NOT_NEGOTIATED; } GST_DEBUG_OBJECT (goom, "allocating output buffer with caps %" GST_PTR_FORMAT, GST_PAD_CAPS (goom->srcpad)); ret = gst_pad_alloc_buffer_and_set_caps (goom->srcpad, GST_BUFFER_OFFSET_NONE, goom->outsize, GST_PAD_CAPS (goom->srcpad), outbuf); if (ret != GST_FLOW_OK) return ret; return GST_FLOW_OK; }
static GstFlowReturn gst_vdp_output_src_pad_alloc_with_caps (GstVdpOutputSrcPad * vdp_pad, GstCaps * caps, GstVdpOutputBuffer ** output_buf, GError ** error) { GstFlowReturn ret; ret = gst_pad_alloc_buffer_and_set_caps ((GstPad *) vdp_pad, 0, 0, caps, (GstBuffer **) output_buf); if (ret != GST_FLOW_OK) return ret; if (!GST_IS_VDP_OUTPUT_BUFFER (*output_buf)) goto invalid_buf; return GST_FLOW_OK; invalid_buf: gst_buffer_unref (GST_BUFFER (*output_buf)); g_set_error (error, GST_STREAM_ERROR, GST_STREAM_ERROR_FAILED, "Sink element returned buffer of wrong type"); return GST_FLOW_ERROR; }
GstFlowReturn gst_base_video_decoder_alloc_src_frame (GstBaseVideoDecoder * base_video_decoder, GstVideoFrame * frame) { GstFlowReturn flow_ret; int num_bytes; gst_base_video_decoder_set_src_caps (base_video_decoder); num_bytes = gst_video_format_get_size (base_video_decoder->state.format, base_video_decoder->state.width, base_video_decoder->state.height); flow_ret = gst_pad_alloc_buffer_and_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_decoder), GST_BUFFER_OFFSET_NONE, num_bytes, GST_PAD_CAPS (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_decoder)), &frame->src_buffer); if (flow_ret != GST_FLOW_OK) { GST_WARNING ("failed to get buffer"); } return flow_ret; }
static int gst_ffmpegdata_write (URLContext * h, unsigned char *buf, int size) { GstProtocolInfo *info; GstBuffer *outbuf; GST_DEBUG ("Writing %d bytes", size); info = (GstProtocolInfo *) h->priv_data; g_return_val_if_fail (h->flags != URL_RDONLY, -EIO); /* create buffer and push data further */ if (gst_pad_alloc_buffer_and_set_caps (info->pad, info->offset, size, GST_PAD_CAPS (info->pad), &outbuf) != GST_FLOW_OK) return 0; memcpy (GST_BUFFER_DATA (outbuf), buf, size); if (gst_pad_push (info->pad, outbuf) != GST_FLOW_OK) return 0; info->offset += size; return size; }
static int gst_wavpack_enc_push_block (void *id, void *data, int32_t count) { GstWavpackEncWriteID *wid = (GstWavpackEncWriteID *) id; GstWavpackEnc *enc = GST_WAVPACK_ENC (wid->wavpack_enc); GstFlowReturn *flow; GstBuffer *buffer; GstPad *pad; guchar *block = (guchar *) data; pad = (wid->correction) ? enc->wvcsrcpad : enc->srcpad; flow = (wid->correction) ? &enc->wvcsrcpad_last_return : &enc-> srcpad_last_return; *flow = gst_pad_alloc_buffer_and_set_caps (pad, GST_BUFFER_OFFSET_NONE, count, GST_PAD_CAPS (pad), &buffer); if (*flow != GST_FLOW_OK) { GST_WARNING_OBJECT (enc, "flow on %s:%s = %s", GST_DEBUG_PAD_NAME (pad), gst_flow_get_name (*flow)); return FALSE; } g_memmove (GST_BUFFER_DATA (buffer), block, count); if (count > sizeof (WavpackHeader) && memcmp (block, "wvpk", 4) == 0) { /* if it's a Wavpack block set buffer timestamp and duration, etc */ WavpackHeader wph; GST_LOG_OBJECT (enc, "got %d bytes of encoded wavpack %sdata", count, (wid->correction) ? "correction " : ""); gst_wavpack_read_header (&wph, block); /* Only set when pushing the first buffer again, in that case * we don't want to delay the buffer or push newsegment events */ if (!wid->passthrough) { /* Only push complete blocks */ if (enc->pending_buffer == NULL) { enc->pending_buffer = buffer; enc->pending_offset = wph.block_index; } else if (enc->pending_offset == wph.block_index) { enc->pending_buffer = gst_buffer_join (enc->pending_buffer, buffer); } else { GST_ERROR ("Got incomplete block, dropping"); gst_buffer_unref (enc->pending_buffer); enc->pending_buffer = buffer; enc->pending_offset = wph.block_index; } if (!(wph.flags & FINAL_BLOCK)) return TRUE; buffer = enc->pending_buffer; enc->pending_buffer = NULL; enc->pending_offset = 0; /* if it's the first wavpack block, send a NEW_SEGMENT event */ if (wph.block_index == 0) { gst_pad_push_event (pad, gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, GST_BUFFER_OFFSET_NONE, 0)); /* save header for later reference, so we can re-send it later on * EOS with fixed up values for total sample count etc. */ if (enc->first_block == NULL && !wid->correction) { enc->first_block = g_memdup (GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)); enc->first_block_size = GST_BUFFER_SIZE (buffer); } } } /* set buffer timestamp, duration, offset, offset_end from * the wavpack header */ GST_BUFFER_TIMESTAMP (buffer) = enc->timestamp_offset + gst_util_uint64_scale_int (GST_SECOND, wph.block_index, enc->samplerate); GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int (GST_SECOND, wph.block_samples, enc->samplerate); GST_BUFFER_OFFSET (buffer) = wph.block_index; GST_BUFFER_OFFSET_END (buffer) = wph.block_index + wph.block_samples; } else { /* if it's something else set no timestamp and duration on the buffer */ GST_DEBUG_OBJECT (enc, "got %d bytes of unknown data", count); GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE; GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE; } /* push the buffer and forward errors */ GST_DEBUG_OBJECT (enc, "pushing buffer with %d bytes", GST_BUFFER_SIZE (buffer)); *flow = gst_pad_push (pad, buffer); if (*flow != GST_FLOW_OK) { GST_WARNING_OBJECT (enc, "flow on %s:%s = %s", GST_DEBUG_PAD_NAME (pad), gst_flow_get_name (*flow)); return FALSE; } return TRUE; }
static void gst_pngdec_task (GstPad * pad) { GstPngDec *pngdec; GstBuffer *buffer = NULL; size_t buffer_size = 0; gint i = 0; png_bytep *rows, inp; png_uint_32 rowbytes; GstFlowReturn ret = GST_FLOW_OK; pngdec = GST_PNGDEC (GST_OBJECT_PARENT (pad)); GST_LOG_OBJECT (pngdec, "read frame"); /* Let libpng come back here on error */ if (setjmp (png_jmpbuf (pngdec->png))) { ret = GST_FLOW_ERROR; goto pause; } /* Set reading callback */ png_set_read_fn (pngdec->png, pngdec, user_read_data); /* Read info */ png_read_info (pngdec->png, pngdec->info); /* Generate the caps and configure */ ret = gst_pngdec_caps_create_and_set (pngdec); if (ret != GST_FLOW_OK) { goto pause; } /* Allocate output buffer */ rowbytes = png_get_rowbytes (pngdec->png, pngdec->info); if (rowbytes > (G_MAXUINT32 - 3) || pngdec->height > G_MAXUINT32 / rowbytes) { ret = GST_FLOW_ERROR; goto pause; } rowbytes = GST_ROUND_UP_4 (rowbytes); buffer_size = pngdec->height * rowbytes; ret = gst_pad_alloc_buffer_and_set_caps (pngdec->srcpad, GST_BUFFER_OFFSET_NONE, buffer_size, GST_PAD_CAPS (pngdec->srcpad), &buffer); if (ret != GST_FLOW_OK) goto pause; rows = (png_bytep *) g_malloc (sizeof (png_bytep) * pngdec->height); inp = GST_BUFFER_DATA (buffer); for (i = 0; i < pngdec->height; i++) { rows[i] = inp; inp += rowbytes; } /* Read the actual picture */ png_read_image (pngdec->png, rows); g_free (rows); /* Push the raw RGB frame */ ret = gst_pad_push (pngdec->srcpad, buffer); if (ret != GST_FLOW_OK) goto pause; /* And we are done */ gst_pad_pause_task (pngdec->sinkpad); gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ()); return; pause: { GST_INFO_OBJECT (pngdec, "pausing task, reason %s", gst_flow_get_name (ret)); gst_pad_pause_task (pngdec->sinkpad); if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) { GST_ELEMENT_ERROR (pngdec, STREAM, FAILED, (_("Internal data stream error.")), ("stream stopped, reason %s", gst_flow_get_name (ret))); gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ()); } } }
static GstFlowReturn gst_jasper_enc_get_data (GstJasperEnc * enc, guint8 * data, GstBuffer ** outbuf) { GstFlowReturn ret = GST_FLOW_OK; jas_stream_t *stream = NULL; gint i; guint size, boxsize; g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR); *outbuf = NULL; boxsize = (enc->mode == GST_JP2ENC_MODE_J2C) ? 8 : 0; if (!(stream = jas_stream_memopen (NULL, 0))) goto fail_stream; for (i = 0; i < enc->channels; ++i) { gint x, y, cwidth, cheight, inc, stride, cmpt; guint8 *row_pix, *in_pix; glong *tb; cmpt = i; inc = enc->inc[i]; stride = enc->stride[i]; cheight = enc->cheight[cmpt]; cwidth = enc->cwidth[cmpt]; GST_LOG_OBJECT (enc, "write component %d<=%d, size %dx%d, offset %d, inc %d, stride %d", i, cmpt, cwidth, cheight, enc->offset[i], inc, stride); row_pix = data + enc->offset[i]; for (y = 0; y < cheight; y++) { in_pix = row_pix; tb = enc->buf; for (x = 0; x < cwidth; x++) { *tb = *in_pix; in_pix += inc; tb++; } if (jas_image_writecmpt2 (enc->image, cmpt, 0, y, cwidth, 1, enc->buf)) goto fail_image; row_pix += stride; } } GST_LOG_OBJECT (enc, "all components written"); if (jas_image_encode (enc->image, stream, enc->fmt, (char *) "sop")) goto fail_encode; GST_LOG_OBJECT (enc, "image encoded"); size = jas_stream_length (stream); ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad, GST_BUFFER_OFFSET_NONE, size + boxsize, GST_PAD_CAPS (enc->srcpad), outbuf); if (ret != GST_FLOW_OK) goto no_buffer; data = GST_BUFFER_DATA (*outbuf); if (jas_stream_flush (stream) || jas_stream_rewind (stream) < 0 || jas_stream_read (stream, data + boxsize, size) < size) goto fail_image_out; if (boxsize) { /* write atom prefix */ GST_WRITE_UINT32_BE (data, size + 8); GST_WRITE_UINT32_LE (data + 4, GST_MAKE_FOURCC ('j', 'p', '2', 'c')); } done: if (stream) jas_stream_close (stream); return ret; /* ERRORS */ fail_stream: { GST_DEBUG_OBJECT (enc, "Failed to create inputstream."); goto fail; } fail_encode: { GST_DEBUG_OBJECT (enc, "Failed to encode image."); goto fail; } fail_image: { GST_DEBUG_OBJECT (enc, "Failed to process input image."); goto fail; } fail_image_out: { GST_DEBUG_OBJECT (enc, "Failed to process encoded image."); goto fail; } fail: { if (*outbuf) gst_buffer_unref (*outbuf); *outbuf = NULL; GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL), (NULL)); ret = GST_FLOW_ERROR; goto done; } no_buffer: { GST_DEBUG_OBJECT (enc, "Failed to create outbuffer - %s", gst_flow_get_name (ret)); goto done; } }
static GstFlowReturn gst_video_test_src_create (GstPushSrc * psrc, GstBuffer ** buffer) { GstVideoTestSrc *src; gulong newsize; GstBuffer *outbuf; GstFlowReturn res; GstClockTime next_time; src = GST_VIDEO_TEST_SRC (psrc); if (G_UNLIKELY (src->fourcc == NULL)) goto not_negotiated; /* 0 framerate and we are at the second frame, eos */ if (G_UNLIKELY (src->rate_numerator == 0 && src->n_frames == 1)) goto eos; newsize = gst_video_test_src_get_size (src, src->width, src->height); g_return_val_if_fail (newsize > 0, GST_FLOW_ERROR); GST_LOG_OBJECT (src, "creating buffer of %lu bytes with %dx%d image for frame %d", newsize, src->width, src->height, (gint) src->n_frames); #ifdef USE_PEER_BUFFERALLOC res = gst_pad_alloc_buffer_and_set_caps (GST_BASE_SRC_PAD (psrc), GST_BUFFER_OFFSET_NONE, newsize, GST_PAD_CAPS (GST_BASE_SRC_PAD (psrc)), &outbuf); if (res != GST_FLOW_OK) goto no_buffer; #else outbuf = gst_buffer_new_and_alloc (newsize); gst_buffer_set_caps (outbuf, GST_PAD_CAPS (GST_BASE_SRC_PAD (psrc))); #endif if (src->pattern_type == GST_VIDEO_TEST_SRC_BLINK) { if (src->n_frames & 0x1) { gst_video_test_src_white (src, (void *) GST_BUFFER_DATA (outbuf), src->width, src->height); } else { gst_video_test_src_black (src, (void *) GST_BUFFER_DATA (outbuf), src->width, src->height); } } else { src->make_image (src, (void *) GST_BUFFER_DATA (outbuf), src->width, src->height); } GST_BUFFER_TIMESTAMP (outbuf) = src->timestamp_offset + src->running_time; GST_BUFFER_OFFSET (outbuf) = src->n_frames; src->n_frames++; GST_BUFFER_OFFSET_END (outbuf) = src->n_frames; if (src->rate_numerator) { next_time = gst_util_uint64_scale_int (src->n_frames * GST_SECOND, src->rate_denominator, src->rate_numerator); GST_BUFFER_DURATION (outbuf) = next_time - src->running_time; } else { next_time = src->timestamp_offset; /* NONE means forever */ GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE; } src->running_time = next_time; *buffer = outbuf; return GST_FLOW_OK; not_negotiated: { GST_ELEMENT_ERROR (src, CORE, NEGOTIATION, (NULL), ("format wasn't negotiated before get function")); return GST_FLOW_NOT_NEGOTIATED; } eos: { GST_DEBUG_OBJECT (src, "eos: 0 framerate, frame %d", (gint) src->n_frames); return GST_FLOW_UNEXPECTED; } no_buffer: { GST_DEBUG_OBJECT (src, "could not allocate buffer, reason %s", gst_flow_get_name (res)); return res; } }
static GstFlowReturn gst_rsvg_decode_image (GstRsvgDec * rsvg, const guint8 * data, guint size, GstBuffer ** buffer) { GstFlowReturn ret = GST_FLOW_OK; cairo_t *cr; cairo_surface_t *surface; RsvgHandle *handle; GError *error = NULL; RsvgDimensionData dimension; gdouble scalex, scaley; GST_LOG_OBJECT (rsvg, "parsing svg"); handle = rsvg_handle_new_from_data (data, size, &error); if (!handle) { GST_ERROR_OBJECT (rsvg, "Failed to parse SVG image: %s", error->message); g_error_free (error); return GST_FLOW_ERROR; } rsvg_handle_get_dimensions (handle, &dimension); if (rsvg->width != dimension.width || rsvg->height != dimension.height) { GstCaps *caps1, *caps2, *caps3; GstStructure *s; GST_LOG_OBJECT (rsvg, "resolution changed, updating caps"); caps1 = gst_caps_copy (gst_pad_get_pad_template_caps (rsvg->srcpad)); caps2 = gst_pad_peer_get_caps (rsvg->srcpad); if (caps2) { caps3 = gst_caps_intersect (caps1, caps2); gst_caps_unref (caps1); gst_caps_unref (caps2); caps1 = caps3; caps3 = NULL; } if (gst_caps_is_empty (caps1)) { GST_ERROR_OBJECT (rsvg, "Unable to negotiate a format"); gst_caps_unref (caps1); g_object_unref (handle); return GST_FLOW_NOT_NEGOTIATED; } caps2 = gst_caps_copy (gst_pad_get_pad_template_caps (rsvg->srcpad)); s = gst_caps_get_structure (caps2, 0); gst_structure_set (s, "width", G_TYPE_INT, dimension.width, "height", G_TYPE_INT, dimension.height, "framerate", GST_TYPE_FRACTION, 0, 1, NULL); caps3 = gst_caps_intersect (caps1, caps2); if (!gst_caps_is_empty (caps3)) { gst_caps_truncate (caps3); gst_pad_set_caps (rsvg->srcpad, caps3); gst_caps_unref (caps1); gst_caps_unref (caps2); gst_caps_unref (caps3); rsvg->width = dimension.width; rsvg->height = dimension.height; } else { gst_caps_unref (caps2); gst_caps_unref (caps3); gst_caps_truncate (caps1); s = gst_caps_get_structure (caps1, 0); gst_structure_set (s, "framerate", GST_TYPE_FRACTION, 0, 1, NULL); if (!gst_caps_is_fixed (caps1) && (!gst_structure_fixate_field_nearest_int (s, "width", dimension.width) || !gst_structure_fixate_field_nearest_int (s, "height", dimension.height))) { g_object_unref (handle); GST_ERROR_OBJECT (rsvg, "Failed to fixate caps"); return GST_FLOW_NOT_NEGOTIATED; } gst_pad_set_caps (rsvg->srcpad, caps1); gst_structure_get_int (s, "width", &rsvg->width); gst_structure_get_int (s, "height", &rsvg->height); gst_caps_unref (caps1); } } if ((ret = gst_pad_alloc_buffer_and_set_caps (rsvg->srcpad, GST_BUFFER_OFFSET_NONE, rsvg->width * rsvg->height * 4, GST_PAD_CAPS (rsvg->srcpad), buffer)) != GST_FLOW_OK) { g_object_unref (handle); GST_ERROR_OBJECT (rsvg, "Buffer allocation failed %s", gst_flow_get_name (ret)); return ret; } GST_LOG_OBJECT (rsvg, "render image at %d x %d", rsvg->height, rsvg->width); surface = cairo_image_surface_create_for_data (GST_BUFFER_DATA (*buffer), CAIRO_FORMAT_ARGB32, rsvg->width, rsvg->height, rsvg->width * 4); cr = cairo_create (surface); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); cairo_paint (cr); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0); scalex = scaley = 1.0; if (rsvg->width != dimension.width) { scalex = ((gdouble) rsvg->width) / ((gdouble) dimension.width); } if (rsvg->height != dimension.height) { scaley = ((gdouble) rsvg->height) / ((gdouble) dimension.height); } cairo_scale (cr, scalex, scaley); rsvg_handle_render_cairo (handle, cr); g_object_unref (handle); cairo_destroy (cr); cairo_surface_destroy (surface); /* Now unpremultiply Cairo's ARGB to match GStreamer's */ gst_rsvg_decode_unpremultiply (GST_BUFFER_DATA (*buffer), rsvg->width, rsvg->height); return ret; }
static GstFlowReturn gst_gdk_pixbuf_flush (GstGdkPixbuf * filter) { GstBuffer *outbuf; GdkPixbuf *pixbuf; int y; guint8 *out_pix; guint8 *in_pix; int in_rowstride; GstFlowReturn ret; GstCaps *caps = NULL; gint n_channels; pixbuf = gdk_pixbuf_loader_get_pixbuf (filter->pixbuf_loader); if (pixbuf == NULL) goto no_pixbuf; if (filter->image_size == 0) { filter->width = gdk_pixbuf_get_width (pixbuf); filter->height = gdk_pixbuf_get_height (pixbuf); filter->rowstride = gdk_pixbuf_get_rowstride (pixbuf); filter->image_size = filter->rowstride * filter->height; n_channels = gdk_pixbuf_get_n_channels (pixbuf); switch (n_channels) { case 3: caps = gst_caps_from_string (GST_VIDEO_CAPS_RGB); break; case 4: caps = gst_caps_from_string (GST_VIDEO_CAPS_RGBA); break; default: goto channels_not_supported; } gst_caps_set_simple (caps, "width", G_TYPE_INT, filter->width, "height", G_TYPE_INT, filter->height, "framerate", GST_TYPE_FRACTION, filter->framerate_numerator, filter->framerate_denominator, NULL); GST_DEBUG ("Set size to %dx%d", filter->width, filter->height); gst_pad_set_caps (filter->srcpad, caps); gst_caps_unref (caps); } ret = gst_pad_alloc_buffer_and_set_caps (filter->srcpad, GST_BUFFER_OFFSET_NONE, filter->image_size, GST_PAD_CAPS (filter->srcpad), &outbuf); if (ret != GST_FLOW_OK) goto no_buffer; GST_BUFFER_TIMESTAMP (outbuf) = filter->last_timestamp; GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE; in_pix = gdk_pixbuf_get_pixels (pixbuf); in_rowstride = gdk_pixbuf_get_rowstride (pixbuf); out_pix = GST_BUFFER_DATA (outbuf); /* FIXME, last line might not have rowstride pixels */ for (y = 0; y < filter->height; y++) { memcpy (out_pix, in_pix, filter->rowstride); in_pix += in_rowstride; out_pix += filter->rowstride; } GST_DEBUG ("pushing... %d bytes", GST_BUFFER_SIZE (outbuf)); ret = gst_pad_push (filter->srcpad, outbuf); if (ret != GST_FLOW_OK) GST_DEBUG_OBJECT (filter, "flow: %s", gst_flow_get_name (ret)); return ret; /* ERRORS */ no_pixbuf: { GST_ELEMENT_ERROR (filter, STREAM, DECODE, (NULL), ("error geting pixbuf")); return GST_FLOW_ERROR; } channels_not_supported: { GST_ELEMENT_ERROR (filter, STREAM, DECODE, (NULL), ("%d channels not supported", n_channels)); return GST_FLOW_ERROR; } no_buffer: { GST_DEBUG ("Failed to create outbuffer - %s", gst_flow_get_name (ret)); return ret; } }