Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
/* 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;
}
Пример #6
0
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;
}
Пример #7
0
/* 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;
}
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #10
0
/** 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);
}
Пример #11
0
/**
 * 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;
}
Пример #12
0
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;
}
Пример #14
0
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;
}
Пример #16
0
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;
}
Пример #17
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));
}
Пример #19
0
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;
}
Пример #20
0
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);
}
Пример #21
0
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;
}
Пример #22
0
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;
}
Пример #23
0
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;
}
Пример #24
0
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;
}
Пример #25
0
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;
}
Пример #26
0
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 ());
    }
  }
}
Пример #27
0
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;
    }
}
Пример #28
0
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;
  }
}
Пример #29
0
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;
    }
}