static GstFlowReturn gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf) { GstShmSink *self = GST_SHM_SINK (bsink); int rv; GstMapInfo map; GST_OBJECT_LOCK (self); while (self->wait_for_connection && !self->clients) { g_cond_wait (self->cond, GST_OBJECT_GET_LOCK (self)); if (self->unlock) { GST_OBJECT_UNLOCK (self); return GST_FLOW_FLUSHING; } } while (!gst_shm_sink_can_render (self, GST_BUFFER_TIMESTAMP (buf))) { g_cond_wait (self->cond, GST_OBJECT_GET_LOCK (self)); if (self->unlock) { GST_OBJECT_UNLOCK (self); return GST_FLOW_FLUSHING; } } gst_buffer_map (buf, &map, GST_MAP_READ); rv = sp_writer_send_buf (self->pipe, (char *) map.data, map.size, GST_BUFFER_TIMESTAMP (buf)); gst_buffer_unmap (buf, &map); if (rv == -1) { ShmBlock *block = NULL; gchar *shmbuf = NULL; while ((block = sp_writer_alloc_block (self->pipe, gst_buffer_get_size (buf))) == NULL) { g_cond_wait (self->cond, GST_OBJECT_GET_LOCK (self)); if (self->unlock) { GST_OBJECT_UNLOCK (self); return GST_FLOW_FLUSHING; } } while (self->wait_for_connection && !self->clients) { g_cond_wait (self->cond, GST_OBJECT_GET_LOCK (self)); if (self->unlock) { sp_writer_free_block (block); GST_OBJECT_UNLOCK (self); return GST_FLOW_FLUSHING; } } shmbuf = sp_writer_block_get_buf (block); gst_buffer_extract (buf, 0, shmbuf, gst_buffer_get_size (buf)); sp_writer_send_buf (self->pipe, shmbuf, gst_buffer_get_size (buf), GST_BUFFER_TIMESTAMP (buf)); sp_writer_free_block (block); } GST_OBJECT_UNLOCK (self); return GST_FLOW_OK; }
static GstMemory * gst_shm_sink_allocator_alloc_locked (GstShmSinkAllocator * self, gsize size, GstAllocationParams * params) { GstMemory *memory = NULL; ShmBlock *block = NULL; gsize maxsize = size + params->prefix + params->padding; gsize align = params->align; /* ensure configured alignment */ align |= gst_memory_alignment; /* allocate more to compensate for alignment */ maxsize += align; block = sp_writer_alloc_block (self->sink->pipe, maxsize); if (block) { GstShmSinkMemory *mymem; gsize aoffset, padding; GST_LOG_OBJECT (self, "Allocated block %p with %" G_GSIZE_FORMAT " bytes at %p", block, size, sp_writer_block_get_buf (block)); mymem = g_slice_new0 (GstShmSinkMemory); memory = GST_MEMORY_CAST (mymem); mymem->data = sp_writer_block_get_buf (block); mymem->sink = gst_object_ref (self->sink); mymem->block = block; /* do alignment */ if ((aoffset = ((guintptr) mymem->data & align))) { aoffset = (align + 1) - aoffset; mymem->data += aoffset; maxsize -= aoffset; } if (params->prefix && (params->flags & GST_MEMORY_FLAG_ZERO_PREFIXED)) memset (mymem->data, 0, params->prefix); padding = maxsize - (params->prefix + size); if (padding && (params->flags & GST_MEMORY_FLAG_ZERO_PADDED)) memset (mymem->data + params->prefix + size, 0, padding); gst_memory_init (memory, params->flags, GST_ALLOCATOR_CAST (g_object_ref (self)), NULL, maxsize, align, params->prefix, size); } return memory; }
static GstFlowReturn gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf) { GstShmSink *self = GST_SHM_SINK (bsink); int rv; GST_OBJECT_LOCK (self); while (self->wait_for_connection && !self->clients) { g_cond_wait (self->cond, GST_OBJECT_GET_LOCK (self)); if (self->unlock) { GST_OBJECT_UNLOCK (self); return GST_FLOW_WRONG_STATE; } } rv = sp_writer_send_buf (self->pipe, (char *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); if (rv == -1) { ShmBlock *block = NULL; gchar *shmbuf = NULL; while ((block = sp_writer_alloc_block (self->pipe, GST_BUFFER_SIZE (buf))) == NULL) { g_cond_wait (self->cond, GST_OBJECT_GET_LOCK (self)); if (self->unlock) { GST_OBJECT_UNLOCK (self); return GST_FLOW_WRONG_STATE; } } while (self->wait_for_connection && !self->clients) { g_cond_wait (self->cond, GST_OBJECT_GET_LOCK (self)); if (self->unlock) { sp_writer_free_block (block); GST_OBJECT_UNLOCK (self); return GST_FLOW_WRONG_STATE; } } shmbuf = sp_writer_block_get_buf (block); memcpy (shmbuf, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); sp_writer_send_buf (self->pipe, shmbuf, GST_BUFFER_SIZE (buf)); sp_writer_free_block (block); } GST_OBJECT_UNLOCK (self); return GST_FLOW_OK; }
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; }
/** * shm_writer_send_buffer * @self: the #ShmWriter with which to send the data buffer * @buffer: the data buffer to send to all connected clients * @len: the length of the data @buffer * * Sends a buffer of data to all connected clients. The data is internally * copied into the appropriate shm area so the passed buffer doesn't need * to be saved. * * Returns: the number of clients the buffer was successfully sent to or %-1 * on error. This number only signifies that it was sent successfully, * not that the clients processed it successfully. */ int shm_writer_send_buffer (ShmWriter *self, const gchar *buffer, gsize len) { ShmWriterPrivate *priv = self->priv; ShmBlock *block; gchar *buf; int ret; if (!priv->open) { g_debug ("ShmWriter not open"); return SHM_WRITER_FAILURE; } /* Allocating, copying, and freeing all this may seem silly, * but the data needs to be in the correct range in memory * in order to share it with other processes */ g_mutex_lock (priv->lock); block = sp_writer_alloc_block (priv->writer, len); if (block == NULL) { g_debug ("ShmWriter: unable to allocate block"); g_mutex_unlock (priv->lock); return SHM_WRITER_FAILURE; } buf = sp_writer_block_get_buf (block); memcpy (buf, buffer, len); ret = sp_writer_send_buf (priv->writer, buf, len); sp_writer_free_block (block); g_mutex_unlock (priv->lock); return ret; }