Пример #1
0
/**
 * gst_buffer_new_and_alloc:
 * @size: the size of the new buffer's data.
 *
 * Creates a newly allocated buffer with data of the given size.
 * The buffer memory is not cleared. If the requested amount of
 * memory can't be allocated, the program will abort. Use
 * gst_buffer_try_new_and_alloc() if you want to handle this case
 * gracefully or have gotten the size to allocate from an untrusted
 * source such as a media stream.
 * 
 *
 * Note that when @size == 0, the buffer data pointer will be NULL.
 *
 * MT safe.
 * Returns: the new #GstBuffer.
 */
GstBuffer *
gst_buffer_new_and_alloc (guint size)
{
  GstBuffer *newbuf;

  newbuf = gst_buffer_new ();

#ifdef HAVE_POSIX_MEMALIGN
  {
    gpointer memptr = NULL;

    if (G_LIKELY (size)) {
      if (G_UNLIKELY (!aligned_malloc (&memptr, size))) {
        /* terminate on error like g_memdup() would */
        g_error ("%s: failed to allocate %u bytes", G_STRLOC, size);
      }
    }
    newbuf->malloc_data = (guint8 *) memptr;
    GST_BUFFER_FREE_FUNC (newbuf) = free;
  }
#else
  newbuf->malloc_data = g_malloc (size);
#endif
  GST_BUFFER_DATA (newbuf) = newbuf->malloc_data;
  GST_BUFFER_SIZE (newbuf) = size;

  GST_CAT_LOG (GST_CAT_BUFFER, "new %p of size %d", newbuf, size);

  return newbuf;
}
Пример #2
0
static void
gst_buffer_init (GstBuffer * buffer)
{
  GST_CAT_LOG (GST_CAT_BUFFER, "init %p", buffer);

  GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
  GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
  GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE;
  GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE;
  GST_BUFFER_FREE_FUNC (buffer) = g_free;
}
Пример #3
0
/* takes the reference */
GstBuffer *
gst_schro_wrap_schro_buffer (SchroBuffer * buffer)
{
  GstBuffer *gstbuf;

#ifdef GST_BUFFER_FREE_FUNC
  gstbuf = gst_buffer_new ();
  GST_BUFFER_DATA (gstbuf) = buffer->data;
  GST_BUFFER_SIZE (gstbuf) = buffer->length;
  GST_BUFFER_MALLOCDATA (gstbuf) = (void *) buffer;
  GST_BUFFER_FREE_FUNC (gstbuf) = schro_buf_free_func;
#else
  gstbuf = gst_buffer_new_and_alloc (buffer->length);
  memcpy (GST_BUFFER_DATA (gstbuf), buffer->data, buffer->length);
#endif

  return gstbuf;
}
Пример #4
0
static GstFlowReturn
gst_shm_sink_buffer_alloc (GstBaseSink * sink, guint64 offset, guint size,
    GstCaps * caps, GstBuffer ** out_buf)
{
  GstShmSink *self = GST_SHM_SINK (sink);
  GstBuffer *buffer;
  ShmBlock *block = NULL;
  gpointer buf = NULL;

  GST_OBJECT_LOCK (self);
  block = sp_writer_alloc_block (self->pipe, size);
  if (block) {
    buf = sp_writer_block_get_buf (block);
    g_object_ref (self);
  }
  GST_OBJECT_UNLOCK (self);

  if (block) {
    buffer = gst_buffer_new ();
    GST_BUFFER_DATA (buffer) = buf;
    GST_BUFFER_MALLOCDATA (buffer) = (guint8 *) block;
    GST_BUFFER_FREE_FUNC (buffer) =
        GST_DEBUG_FUNCPTR (gst_shm_sink_free_buffer);
    GST_BUFFER_SIZE (buffer) = size;
    GST_LOG_OBJECT (self,
        "Allocated buffer of %u bytes from shared memory at %p", size, buf);
  } else {
    buffer = gst_buffer_new_and_alloc (size);
    GST_LOG_OBJECT (self, "Not enough shared memory for buffer of %u bytes, "
        "allocating using standard allocator", size);
  }

  GST_BUFFER_OFFSET (buffer) = offset;
  gst_buffer_set_caps (buffer, caps);

  *out_buf = buffer;

  return GST_FLOW_OK;
}
Пример #5
0
/**
 * gst_buffer_try_new_and_alloc:
 * @size: the size of the new buffer's data.
 *
 * Tries to create a newly allocated buffer with data of the given size. If
 * the requested amount of memory can't be allocated, NULL will be returned.
 * The buffer memory is not cleared.
 *
 * Note that when @size == 0, the buffer data pointer will be NULL.
 *
 * MT safe.
 *
 * Returns: a new #GstBuffer, or NULL if the memory couldn't be allocated.
 *
 * Since: 0.10.13
 */
GstBuffer *
gst_buffer_try_new_and_alloc (guint size)
{
  GstBuffer *newbuf;
  guint8 *malloc_data;
#ifdef HAVE_POSIX_MEMALIGN
  gpointer memptr = NULL;

  if (G_LIKELY (size)) {
    if (G_UNLIKELY (!aligned_malloc (&memptr, size))) {
      GST_CAT_WARNING (GST_CAT_BUFFER, "failed to allocate %d bytes", size);
      return NULL;
    }
  }
  malloc_data = (guint8 *) memptr;
#else
  malloc_data = g_try_malloc (size);

  if (G_UNLIKELY (malloc_data == NULL && size != 0)) {
    GST_CAT_WARNING (GST_CAT_BUFFER, "failed to allocate %d bytes", size);
    return NULL;
  }
#endif

  /* FIXME: there's no g_type_try_create_instance() in GObject yet, so this
   * will still abort if a new GstBuffer structure can't be allocated */
  newbuf = gst_buffer_new ();

  GST_BUFFER_MALLOCDATA (newbuf) = malloc_data;
  GST_BUFFER_DATA (newbuf) = malloc_data;
  GST_BUFFER_SIZE (newbuf) = size;
#ifdef HAVE_POSIX_MEMALIGN
  GST_BUFFER_FREE_FUNC (newbuf) = free;
#endif

  GST_CAT_LOG (GST_CAT_BUFFER, "new %p of size %d", newbuf, size);

  return newbuf;
}
Пример #6
0
static GstBuffer *
_gst_buffer_copy (GstBuffer * buffer)
{
  GstBuffer *copy;

  g_return_val_if_fail (buffer != NULL, NULL);

  /* create a fresh new buffer */
  copy = gst_buffer_new ();

  /* we simply copy everything from our parent */
#ifdef HAVE_POSIX_MEMALIGN
  {
    gpointer memptr = NULL;

    if (G_LIKELY (buffer->size)) {
      if (G_UNLIKELY (!aligned_malloc (&memptr, buffer->size))) {
        /* terminate on error like g_memdup() would */
        g_error ("%s: failed to allocate %u bytes", G_STRLOC, buffer->size);
      } else {
        memcpy (memptr, buffer->data, buffer->size);
      }
    }
    copy->data = (guint8 *) memptr;
    GST_BUFFER_FREE_FUNC (copy) = free;
  }
#else
  copy->data = g_memdup (buffer->data, buffer->size);
#endif

  /* make sure it gets freed (even if the parent is subclassed, we return a
     normal buffer) */
  copy->malloc_data = copy->data;
  copy->size = buffer->size;

  gst_buffer_copy_metadata (copy, buffer, GST_BUFFER_COPY_ALL);

  return copy;
}
Пример #7
0
static GstFlowReturn
gst_shm_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
{
  GstShmSrc *self = GST_SHM_SRC (psrc);
  gchar *buf = NULL;
  int rv = 0;
  struct GstShmBuffer *gsb;

  do {
    if (gst_poll_wait (self->poll, GST_CLOCK_TIME_NONE) < 0) {
      if (errno == EBUSY)
        return GST_FLOW_WRONG_STATE;
      GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed to read from shmsrc"),
          ("Poll failed on fd: %s", strerror (errno)));
      return GST_FLOW_ERROR;
    }

    if (self->unlocked)
      return GST_FLOW_WRONG_STATE;

    if (gst_poll_fd_has_closed (self->poll, &self->pollfd)) {
      GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed to read from shmsrc"),
          ("Control socket has closed"));
      return GST_FLOW_ERROR;
    }

    if (gst_poll_fd_has_error (self->poll, &self->pollfd)) {
      GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed to read from shmsrc"),
          ("Control socket has error"));
      return GST_FLOW_ERROR;
    }

    if (gst_poll_fd_can_read (self->poll, &self->pollfd)) {
      buf = NULL;
      GST_LOG_OBJECT (self, "Reading from pipe");
      GST_OBJECT_LOCK (self);
      rv = sp_client_recv (self->pipe->pipe, &buf);
      GST_OBJECT_UNLOCK (self);
      if (rv < 0) {
        GST_ELEMENT_ERROR (self, RESOURCE, READ, ("Failed to read from shmsrc"),
            ("Error reading control data: %d", rv));
        return GST_FLOW_ERROR;
      }
    }
  } while (buf == NULL);

  GST_LOG_OBJECT (self, "Got buffer %p of size %d", buf, rv);

  gsb = g_slice_new0 (struct GstShmBuffer);
  gsb->buf = buf;
  gsb->pipe = self->pipe;
  gst_shm_pipe_inc (self->pipe);

  *outbuf = gst_buffer_new ();
  GST_BUFFER_FLAG_SET (*outbuf, GST_BUFFER_FLAG_READONLY);
  GST_BUFFER_DATA (*outbuf) = (guint8 *) buf;
  GST_BUFFER_SIZE (*outbuf) = rv;
  GST_BUFFER_MALLOCDATA (*outbuf) = (guint8 *) gsb;
  GST_BUFFER_FREE_FUNC (*outbuf) = free_buffer;

  return GST_FLOW_OK;
}
static void
gst_decklink_src_task (void *priv)
{
    GstDecklinkSrc *decklinksrc = GST_DECKLINK_SRC (priv);
    GstBuffer *buffer;
    GstBuffer *audio_buffer;
    IDeckLinkVideoInputFrame *video_frame;
    IDeckLinkAudioInputPacket *audio_frame;
    void *data;
    int n_samples;
    GstFlowReturn ret;
    const GstDecklinkMode *mode;

    GST_DEBUG_OBJECT (decklinksrc, "task");

    g_mutex_lock (decklinksrc->mutex);
    while (decklinksrc->video_frame == NULL && !decklinksrc->stop) {
        g_cond_wait (decklinksrc->cond, decklinksrc->mutex);
    }
    video_frame = decklinksrc->video_frame;
    audio_frame = decklinksrc->audio_frame;
    decklinksrc->video_frame = NULL;
    decklinksrc->audio_frame = NULL;
    g_mutex_unlock (decklinksrc->mutex);

    if (decklinksrc->stop) {
        GST_DEBUG ("stopping task");
        return;
    }

    /* warning on dropped frames */
    if (decklinksrc->dropped_frames - decklinksrc->dropped_frames_old > 0) {
        GST_ELEMENT_WARNING (decklinksrc, RESOURCE, READ,
                             ("Dropped %d frame(s), for a total of %d frame(s)",
                              decklinksrc->dropped_frames - decklinksrc->dropped_frames_old,
                              decklinksrc->dropped_frames),
                             (NULL));
        decklinksrc->dropped_frames_old = decklinksrc->dropped_frames;
    }

    mode = gst_decklink_get_mode (decklinksrc->mode);

    video_frame->GetBytes (&data);
    if (decklinksrc->copy_data) {
        buffer = gst_buffer_new_and_alloc (mode->width * mode->height * 2);

        memcpy (GST_BUFFER_DATA (buffer), data, mode->width * mode->height * 2);

        video_frame->Release ();
    } else {
        buffer = gst_buffer_new ();
        GST_BUFFER_SIZE (buffer) = mode->width * mode->height * 2;

        GST_BUFFER_DATA (buffer) = (guint8 *) data;

        GST_BUFFER_FREE_FUNC (buffer) = video_frame_free;
        GST_BUFFER_MALLOCDATA (buffer) = (guint8 *) video_frame;
    }

    GST_BUFFER_TIMESTAMP (buffer) =
        gst_util_uint64_scale_int (decklinksrc->frame_num * GST_SECOND,
                                   mode->fps_d, mode->fps_n);
    GST_BUFFER_DURATION (buffer) =
        gst_util_uint64_scale_int ((decklinksrc->frame_num + 1) * GST_SECOND,
                                   mode->fps_d, mode->fps_n) - GST_BUFFER_TIMESTAMP (buffer);
    GST_BUFFER_OFFSET (buffer) = decklinksrc->frame_num;
    GST_BUFFER_OFFSET_END (buffer) = decklinksrc->frame_num;
    if (decklinksrc->frame_num == 0) {
        GstEvent *event;
        gboolean ret;

        GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);

        event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0,
                                           GST_CLOCK_TIME_NONE, 0);

        ret = gst_pad_push_event (decklinksrc->videosrcpad, event);
        if (!ret) {
            GST_ERROR_OBJECT (decklinksrc, "new segment event ret=%d", ret);
            return;
        }
    }

    if (decklinksrc->video_caps == NULL) {
        decklinksrc->video_caps = gst_decklink_mode_get_caps (decklinksrc->mode);
    }
    gst_buffer_set_caps (buffer, decklinksrc->video_caps);

    ret = gst_pad_push (decklinksrc->videosrcpad, buffer);
    if (ret != GST_FLOW_OK) {
        GST_ELEMENT_ERROR (decklinksrc, CORE, NEGOTIATION, (NULL), (NULL));
    }

    if (gst_pad_is_linked (decklinksrc->audiosrcpad)) {
        n_samples = audio_frame->GetSampleFrameCount ();
        audio_frame->GetBytes (&data);
        audio_buffer = gst_buffer_new_and_alloc (n_samples * 2 * 2);
        memcpy (GST_BUFFER_DATA (audio_buffer), data, n_samples * 2 * 2);

        GST_BUFFER_TIMESTAMP (audio_buffer) =
            gst_util_uint64_scale_int (decklinksrc->num_audio_samples * GST_SECOND,
                                       1, 48000);
        GST_BUFFER_DURATION (audio_buffer) =
            gst_util_uint64_scale_int ((decklinksrc->num_audio_samples +
                                        n_samples) * GST_SECOND, 1,
                                       48000) - GST_BUFFER_TIMESTAMP (audio_buffer);
        decklinksrc->num_audio_samples += n_samples;

        if (decklinksrc->audio_caps == NULL) {
            decklinksrc->audio_caps = gst_caps_new_simple ("audio/x-raw-int",
                                      "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
                                      "signed", G_TYPE_BOOLEAN, TRUE,
                                      "depth", G_TYPE_INT, 16,
                                      "width", G_TYPE_INT, 16,
                                      "channels", G_TYPE_INT, 2, "rate", G_TYPE_INT, 48000, NULL);
        }
        gst_buffer_set_caps (audio_buffer, decklinksrc->audio_caps);

        ret = gst_pad_push (decklinksrc->audiosrcpad, audio_buffer);
        if (ret != GST_FLOW_OK) {
            GST_ELEMENT_ERROR (decklinksrc, CORE, NEGOTIATION, (NULL), (NULL));
        }
    }
    audio_frame->Release ();
}
Пример #9
0
static gboolean
gst_gdk_pixbuf_overlay_load_image (GstGdkPixbufOverlay * overlay, GError ** err)
{
  GdkPixbuf *pixbuf;
  guint8 *pixels, *p;
  gint width, height, stride, w, h;

  pixbuf = gdk_pixbuf_new_from_file (overlay->location, err);

  if (pixbuf == NULL)
    return FALSE;

  if (!gdk_pixbuf_get_has_alpha (pixbuf)) {
    GdkPixbuf *alpha_pixbuf;

    /* FIXME: we could do this much more efficiently ourselves below, but
     * we're lazy for now */
    /* FIXME: perhaps expose substitute_color via properties */
    alpha_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
    g_object_unref (pixbuf);
    pixbuf = alpha_pixbuf;
  }

  width = gdk_pixbuf_get_width (pixbuf);
  height = gdk_pixbuf_get_height (pixbuf);
  stride = gdk_pixbuf_get_rowstride (pixbuf);
  pixels = gdk_pixbuf_get_pixels (pixbuf);

  /* the memory layout in GdkPixbuf is R-G-B-A, we want:
   *  - B-G-R-A on little-endian platforms
   *  - A-R-G-B on big-endian platforms
   */
  for (h = 0; h < height; ++h) {
    p = pixels + (h * stride);
    for (w = 0; w < width; ++w) {
      guint8 tmp;

      /* R-G-B-A ==> B-G-R-A */
      tmp = p[0];
      p[0] = p[2];
      p[2] = tmp;

      if (G_BYTE_ORDER == G_BIG_ENDIAN) {
        /* B-G-R-A ==> A-R-G-B */
        /* we can probably assume sane alignment */
        *((guint32 *) p) = GUINT32_SWAP_LE_BE (*((guint32 *) p));
      }

      p += 4;
    }
  }

  overlay->pixels = gst_buffer_new ();
  GST_BUFFER_DATA (overlay->pixels) = pixels;
  /* assume we have row padding even for the last row */
  GST_BUFFER_SIZE (overlay->pixels) = height * stride;
  /* transfer ownership of pixbuf to buffer */
  GST_BUFFER_MALLOCDATA (overlay->pixels) = (guint8 *) pixbuf;
  GST_BUFFER_FREE_FUNC (overlay->pixels) = (GFreeFunc) g_object_unref;

  overlay->pixels_width = width;
  overlay->pixels_height = height;
  overlay->pixels_stride = stride;

  overlay->update_composition = TRUE;

  GST_INFO_OBJECT (overlay, "Loaded image, %d x %d", width, height);
  return TRUE;
}