/** * 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; }
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; }
/* 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; }
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; }
/** * 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; }
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; }
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 (); }
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; }