static GstMemory * gst_egl_image_allocator_wrap (GstEGLImageAllocator * allocator, GstGLContextEGL * context, EGLImageKHR image, GstVideoGLTextureType type, GstMemoryFlags flags, gsize size, gpointer user_data, GstEGLImageDestroyNotify user_data_destroy) { GstEGLImageMemory *mem = NULL; g_return_val_if_fail (context != NULL, NULL); g_return_val_if_fail (image != EGL_NO_IMAGE_KHR, NULL); if (!allocator) { allocator = gst_egl_image_allocator_obtain (); } mem = g_slice_new (GstEGLImageMemory); gst_memory_init (GST_MEMORY_CAST (mem), flags, GST_ALLOCATOR (allocator), NULL, size, 0, 0, size); gst_object_unref (allocator); mem->context = gst_object_ref (context); mem->image = image; mem->type = type; mem->orientation = GST_VIDEO_GL_TEXTURE_ORIENTATION_X_NORMAL_Y_NORMAL; mem->user_data = user_data; mem->user_data_destroy = user_data_destroy; return GST_MEMORY_CAST (mem); }
GstV4l2MemoryGroup * gst_v4l2_allocator_alloc_dmabufin (GstV4l2Allocator * allocator) { GstV4l2MemoryGroup *group; gint i; g_return_val_if_fail (allocator->memory == V4L2_MEMORY_DMABUF, NULL); group = gst_v4l2_allocator_alloc (allocator); if (group == NULL) return NULL; GST_LOG_OBJECT (allocator, "allocating empty DMABUF import group"); for (i = 0; i < group->n_mem; i++) { if (group->mem[i] == NULL) { group->mem[i] = (GstMemory *) _v4l2mem_new (0, GST_ALLOCATOR (allocator), NULL, 0, 0, 0, 0, i, NULL, -1, group); } else { /* Take back the allocator reference */ gst_object_ref (allocator); } group->mems_allocated++; } gst_v4l2_allocator_clear_dmabufin (allocator, group); return group; }
static gboolean gst_shmdata_sink_propose_allocation (GstBaseSink * sink, GstQuery * query) { GstShmdataSink *self = GST_SHMDATA_SINK (sink); if (self->allocator) gst_query_add_allocation_param (query, GST_ALLOCATOR (self->allocator), NULL); return TRUE; }
static void gst_shm_sink_allocator_init (GstShmSinkAllocator * self) { GstAllocator *allocator = GST_ALLOCATOR (self); allocator->mem_map = gst_shm_sink_allocator_mem_map; allocator->mem_unmap = gst_shm_sink_allocator_mem_unmap; allocator->mem_share = gst_shm_sink_allocator_mem_share; allocator->mem_is_span = gst_shm_sink_allocator_mem_is_span; }
GstV4l2MemoryGroup * gst_v4l2_allocator_alloc_mmap (GstV4l2Allocator * allocator) { GstV4l2Object *obj = allocator->obj; GstV4l2MemoryGroup *group; gint i; g_return_val_if_fail (allocator->memory == V4L2_MEMORY_MMAP, NULL); group = gst_v4l2_allocator_alloc (allocator); if (group == NULL) return NULL; for (i = 0; i < group->n_mem; i++) { if (group->mem[i] == NULL) { gpointer data; data = obj->mmap (NULL, group->planes[i].length, PROT_READ | PROT_WRITE, MAP_SHARED, obj->video_fd, group->planes[i].m.mem_offset); if (data == MAP_FAILED) goto mmap_failed; GST_LOG_OBJECT (allocator, "mmap buffer length %d, data offset %d, plane %d", group->planes[i].length, group->planes[i].data_offset, i); group->mem[i] = (GstMemory *) _v4l2mem_new (0, GST_ALLOCATOR (allocator), NULL, group->planes[i].length, 0, 0, group->planes[i].length, i, data, -1, group); } else { /* Take back the allocator reference */ gst_object_ref (allocator); } group->mems_allocated++; } /* Ensure group size. Unlike GST, v4l2 have size (bytesused) initially set * to 0. As length might be bigger then the expected size exposed in the * format, we simply set bytesused initially and reset it here for * simplicity */ gst_v4l2_allocator_reset_size (allocator, group); return group; mmap_failed: { GST_ERROR_OBJECT (allocator, "Failed to mmap buffer: %s", g_strerror (errno)); _cleanup_failed_alloc (allocator, group); return NULL; } }
static void gst_imx_pxp_allocator_init(GstImxPxPAllocator *allocator) { GstAllocator *base = GST_ALLOCATOR(allocator); base->mem_type = GST_IMX_PXP_ALLOCATOR_MEM_TYPE; if (!gst_imx_pxp_open()) { GST_ERROR_OBJECT(allocator, "could not open PxP device"); return; } }
GstAllocator * gst_mir_image_allocator_obtain (void) { static GOnce once = G_ONCE_INIT; g_once (&once, gst_mir_image_allocator_init_instance, NULL); g_return_val_if_fail (once.retval != NULL, NULL); return GST_ALLOCATOR (g_object_ref (once.retval)); }
void gst_test_phys_mem_allocator_init(GstTestPhysMemAllocator *allocator) { GstAllocator *parent = GST_ALLOCATOR(allocator); GST_INFO_OBJECT(allocator, "initializing physical memory allocator"); parent->mem_type = NULL; parent->mem_map = GST_DEBUG_FUNCPTR(gst_test_phys_mem_allocator_map); parent->mem_unmap = GST_DEBUG_FUNCPTR(gst_test_phys_mem_allocator_unmap); parent->mem_copy = GST_DEBUG_FUNCPTR(gst_test_phys_mem_allocator_copy); parent->mem_share = GST_DEBUG_FUNCPTR(gst_test_phys_mem_allocator_share); parent->mem_is_span = GST_DEBUG_FUNCPTR(gst_test_phys_mem_allocator_is_span); }
GstAllocator * gst_droid_codec_allocator_gralloc_new (GstDroidComponentPort * port) { GstDroidCodecGrallocAllocator *alloc; GST_DEBUG_CATEGORY_INIT (droid_codec_gralloc_debug, "droidcodecgralloc", 0, "droid codec gralloc allocator"); alloc = g_object_new (GST_TYPE_GRALLOC_ALLOCATOR, NULL); alloc->port = port; return GST_ALLOCATOR (alloc); }
static GstGLBuffer * _gl_buffer_alloc_mem (GstGLBufferAllocator * allocator, GstGLBufferAllocationParams * params) { guint alloc_flags = params->parent.alloc_flags; g_return_val_if_fail (alloc_flags & GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_BUFFER, NULL); g_return_val_if_fail (alloc_flags & GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_ALLOC, NULL); return _gl_buffer_new (GST_ALLOCATOR (allocator), NULL, params->parent.context, params->gl_target, params->gl_usage, params->parent.alloc_params, params->parent.alloc_size); }
static GstFlowReturn gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf) { GstShmSink *self = GST_SHM_SINK (bsink); int rv = 0; GstMapInfo map; gboolean need_new_memory = FALSE; GstFlowReturn ret = GST_FLOW_OK; GstMemory *memory = NULL; GstBuffer *sendbuf = NULL; gsize written_bytes; 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); ret = gst_base_sink_wait_preroll (bsink); if (ret == GST_FLOW_OK) GST_OBJECT_LOCK (self); else return ret; } } 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); ret = gst_base_sink_wait_preroll (bsink); if (ret == GST_FLOW_OK) GST_OBJECT_LOCK (self); else return ret; } } if (gst_buffer_n_memory (buf) > 1) { GST_LOG_OBJECT (self, "Buffer %p has %d GstMemory, we only support a single" " one, need to do a memcpy", buf, gst_buffer_n_memory (buf)); need_new_memory = TRUE; } else { memory = gst_buffer_peek_memory (buf, 0); if (memory->allocator != GST_ALLOCATOR (self->allocator)) { need_new_memory = TRUE; GST_LOG_OBJECT (self, "Memory in buffer %p was not allocated by " "%" GST_PTR_FORMAT ", will memcpy", buf, memory->allocator); } } if (need_new_memory) { if (gst_buffer_get_size (buf) > sp_writer_get_max_buf_size (self->pipe)) { gsize area_size = sp_writer_get_max_buf_size (self->pipe); GST_ELEMENT_ERROR (self, RESOURCE, NO_SPACE_LEFT, (NULL), ("Shared memory area of size %" G_GSIZE_FORMAT " is smaller than" "buffer of size %" G_GSIZE_FORMAT, area_size, gst_buffer_get_size (buf))); goto error; } while ((memory = gst_shm_sink_allocator_alloc_locked (self->allocator, gst_buffer_get_size (buf), &self->params)) == NULL) { g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self)); if (self->unlock) { GST_OBJECT_UNLOCK (self); ret = gst_base_sink_wait_preroll (bsink); if (ret == GST_FLOW_OK) GST_OBJECT_LOCK (self); else return ret; } } while (self->wait_for_connection && !self->clients) { g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self)); if (self->unlock) { GST_OBJECT_UNLOCK (self); ret = gst_base_sink_wait_preroll (bsink); if (ret == GST_FLOW_OK) { GST_OBJECT_LOCK (self); } else { gst_memory_unref (memory); return ret; } } } if (!gst_memory_map (memory, &map, GST_MAP_WRITE)) { GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), ("Failed to map memory")); goto error; } GST_DEBUG_OBJECT (self, "Copying %" G_GSIZE_FORMAT " bytes into map of size %" G_GSIZE_FORMAT " bytes.", gst_buffer_get_size (buf), map.size); written_bytes = gst_buffer_extract (buf, 0, map.data, map.size); GST_DEBUG_OBJECT (self, "Copied %" G_GSIZE_FORMAT " bytes.", written_bytes); gst_memory_unmap (memory, &map); sendbuf = gst_buffer_new (); if (!gst_buffer_copy_into (sendbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1)) { GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), ("Failed to copy data into send buffer")); gst_buffer_unref (sendbuf); goto error; } gst_buffer_append_memory (sendbuf, memory); } else { sendbuf = gst_buffer_ref (buf); } if (!gst_buffer_map (sendbuf, &map, GST_MAP_READ)) { GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), ("Failed to map data into send buffer")); goto error; } /* Make the memory readonly as of now as we've sent it to the other side * We know it's not mapped for writing anywhere as we just mapped it for * reading */ rv = sp_writer_send_buf (self->pipe, (char *) map.data, map.size, sendbuf); if (rv == -1) { GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), ("Failed to send data over SHM")); gst_buffer_unmap (sendbuf, &map); goto error; } gst_buffer_unmap (sendbuf, &map); GST_OBJECT_UNLOCK (self); if (rv == 0) { GST_DEBUG_OBJECT (self, "No clients connected, unreffing buffer"); gst_buffer_unref (sendbuf); } return ret; error: GST_OBJECT_UNLOCK (self); return GST_FLOW_ERROR; }
static void gst_fsl_vpu_dec_allocator_init(GstFslVpuDecAllocator *allocator) { GstAllocator *base = GST_ALLOCATOR(allocator); base->mem_type = GST_FSL_VPU_DEC_ALLOCATOR_MEM_TYPE; }
static gboolean gst_gl_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) { GstGLBufferPool *glpool = GST_GL_BUFFER_POOL_CAST (pool); GstGLBufferPoolPrivate *priv = glpool->priv; GstVideoInfo info; GstCaps *caps = NULL; guint min_buffers, max_buffers; guint max_align, n; GstAllocator *allocator = NULL; GstAllocationParams alloc_params; GstGLTextureTarget tex_target; gboolean ret = TRUE; gint p; if (!gst_buffer_pool_config_get_params (config, &caps, NULL, &min_buffers, &max_buffers)) goto wrong_config; if (caps == NULL) goto no_caps; /* now parse the caps from the config */ if (!gst_video_info_from_caps (&info, caps)) goto wrong_caps; GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT, info.width, info.height, caps); if (!gst_buffer_pool_config_get_allocator (config, &allocator, &alloc_params)) goto wrong_config; gst_caps_replace (&priv->caps, caps); if (priv->allocator) gst_object_unref (priv->allocator); if (allocator) { if (!GST_IS_GL_MEMORY_ALLOCATOR (allocator)) { gst_object_unref (allocator); goto wrong_allocator; } else { priv->allocator = gst_object_ref (allocator); } } else { priv->allocator = GST_ALLOCATOR (gst_gl_memory_allocator_get_default (glpool->context)); g_assert (priv->allocator); } priv->add_videometa = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); priv->add_glsyncmeta = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_GL_SYNC_META); if (priv->gl_params) gst_gl_allocation_params_free ((GstGLAllocationParams *) priv->gl_params); priv->gl_params = (GstGLVideoAllocationParams *) gst_buffer_pool_config_get_gl_allocation_params (config); if (!priv->gl_params) priv->gl_params = gst_gl_video_allocation_params_new (glpool->context, &alloc_params, &info, -1, NULL, 0, 0); max_align = alloc_params.align; if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)) { priv->add_videometa = TRUE; gst_buffer_pool_config_get_video_alignment (config, priv->gl_params->valign); for (n = 0; n < GST_VIDEO_MAX_PLANES; ++n) max_align |= priv->gl_params->valign->stride_align[n]; for (n = 0; n < GST_VIDEO_MAX_PLANES; ++n) priv->gl_params->valign->stride_align[n] = max_align; gst_video_info_align (priv->gl_params->v_info, priv->gl_params->valign); gst_buffer_pool_config_set_video_alignment (config, priv->gl_params->valign); } if (alloc_params.align < max_align) { GST_WARNING_OBJECT (pool, "allocation params alignment %u is smaller " "than the max specified video stride alignment %u, fixing", (guint) alloc_params.align, max_align); alloc_params.align = max_align; gst_buffer_pool_config_set_allocator (config, allocator, &alloc_params); if (priv->gl_params->parent.alloc_params) gst_allocation_params_free (priv->gl_params->parent.alloc_params); priv->gl_params->parent.alloc_params = gst_allocation_params_copy (&alloc_params); } { GstStructure *s = gst_caps_get_structure (caps, 0); const gchar *target_str = gst_structure_get_string (s, "texture-target"); gboolean multiple_texture_targets = FALSE; tex_target = priv->gl_params->target; if (target_str) tex_target = gst_gl_texture_target_from_string (target_str); if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_2D)) { if (tex_target && tex_target != GST_GL_TEXTURE_TARGET_2D) multiple_texture_targets = TRUE; tex_target = GST_GL_TEXTURE_TARGET_2D; } if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_RECTANGLE)) { if (tex_target && tex_target != GST_GL_TEXTURE_TARGET_RECTANGLE) multiple_texture_targets = TRUE; tex_target = GST_GL_TEXTURE_TARGET_RECTANGLE; } if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_EXTERNAL_OES)) { if (tex_target && tex_target != GST_GL_TEXTURE_TARGET_EXTERNAL_OES) multiple_texture_targets = TRUE; tex_target = GST_GL_TEXTURE_TARGET_EXTERNAL_OES; } if (!tex_target) tex_target = GST_GL_TEXTURE_TARGET_2D; if (multiple_texture_targets) { GST_WARNING_OBJECT (pool, "Multiple texture targets configured either " "through caps or buffer pool options"); ret = FALSE; } priv->gl_params->target = tex_target; } /* Recalulate the size and offset as we don't add padding between planes. */ priv->gl_params->v_info->size = 0; for (p = 0; p < GST_VIDEO_INFO_N_PLANES (priv->gl_params->v_info); p++) { priv->gl_params->v_info->offset[p] = priv->gl_params->v_info->size; priv->gl_params->v_info->size += gst_gl_get_plane_data_size (priv->gl_params->v_info, priv->gl_params->valign, p); } gst_buffer_pool_config_set_params (config, caps, priv->gl_params->v_info->size, min_buffers, max_buffers); return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config) && ret; /* ERRORS */ wrong_config: { GST_WARNING_OBJECT (pool, "invalid config"); return FALSE; } no_caps: { GST_WARNING_OBJECT (pool, "no caps in config"); return FALSE; } wrong_caps: { GST_WARNING_OBJECT (pool, "failed getting geometry from caps %" GST_PTR_FORMAT, caps); return FALSE; } wrong_allocator: { GST_WARNING_OBJECT (pool, "Incorrect allocator type for this pool"); return FALSE; } }
static void gst_test_vpu_dec_allocator_init(GstTestVpuDecAllocator *allocator) { GstAllocator *base = GST_ALLOCATOR(allocator); base->mem_type = GST_TEST_VPU_DEC_ALLOCATOR_MEM_TYPE; }
static GstFlowReturn gst_shmdata_sink_render (GstBaseSink * bsink, GstBuffer * buf) { GstShmdataSink *self = GST_SHMDATA_SINK (bsink); int rv = 0; GstMapInfo map; gboolean need_new_memory = FALSE; GstFlowReturn ret = GST_FLOW_OK; GstMemory *memory = NULL; GstBuffer *sendbuf = NULL; GST_OBJECT_LOCK (self); if (gst_buffer_n_memory (buf) > 1) { GST_LOG_OBJECT (self, "Buffer %p has %d GstMemory, we only support a single" " one, need to do a memcpy", buf, gst_buffer_n_memory (buf)); need_new_memory = TRUE; } else { memory = gst_buffer_peek_memory (buf, 0); if (memory->allocator != GST_ALLOCATOR (self->allocator)) { need_new_memory = TRUE; GST_LOG_OBJECT (self, "Memory in buffer %p was not allocated by " "%" GST_PTR_FORMAT ", will memcpy", buf, memory->allocator); } } if (need_new_memory) { if (gst_buffer_get_size (buf) > shmdata_get_shmmax(NULL)) { gsize area_size = shmdata_get_shmmax(NULL); GST_OBJECT_UNLOCK (self); GST_ELEMENT_ERROR (self, RESOURCE, NO_SPACE_LEFT, ("Shared memory area is too small"), ("Shared memory area of size %" G_GSIZE_FORMAT " is smaller than" "buffer of size %" G_GSIZE_FORMAT, area_size, gst_buffer_get_size (buf))); return GST_FLOW_ERROR; } while ((memory = gst_shmdata_sink_allocator_alloc_locked (self->allocator, gst_buffer_get_size (buf), &self->params)) == NULL) { g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self)); if (self->unlock) goto flushing; } gst_memory_map (memory, &map, GST_MAP_WRITE); gst_buffer_extract (buf, 0, map.data, map.size); gst_memory_unmap (memory, &map); sendbuf = gst_buffer_new (); gst_buffer_copy_into (sendbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1); gst_buffer_append_memory (sendbuf, memory); } else { sendbuf = gst_buffer_ref (buf); } gst_buffer_map (sendbuf, &map, GST_MAP_READ); /* Make the memory readonly as of now as we've sent it to the other side * We know it's not mapped for writing anywhere as we just mapped it for * reading */ shmdata_notify_clients(self->access, map.size); self->bytes_since_last_request += map.size; shmdata_release_one_write_access(self->access); // wait for client to read and take the write lock self->access = shmdata_get_one_write_access(self->shmwriter); gst_buffer_unmap (sendbuf, &map); GST_OBJECT_UNLOCK (self); GST_DEBUG_OBJECT (self, "No clients connected, unreffing buffer"); gst_buffer_unref (sendbuf); /* If we allocated our own memory, then unmap it */ return ret; flushing: GST_OBJECT_UNLOCK (self); return GST_FLOW_FLUSHING; }
static void gst_gl_composition_overlay_upload (GstGLCompositionOverlay * overlay, GstBuffer * buf) { GstGLMemory *comp_gl_memory = NULL; GstBuffer *comp_buffer = NULL; GstBuffer *overlay_buffer = NULL; GstVideoInfo vinfo; GstVideoMeta *vmeta; GstVideoFrame *comp_frame; GstVideoFrame gl_frame; comp_buffer = gst_video_overlay_rectangle_get_pixels_unscaled_argb (overlay->rectangle, GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA); comp_frame = g_slice_new (GstVideoFrame); vmeta = gst_buffer_get_video_meta (comp_buffer); gst_video_info_set_format (&vinfo, vmeta->format, vmeta->width, vmeta->height); vinfo.stride[0] = vmeta->stride[0]; if (gst_video_frame_map (comp_frame, &vinfo, comp_buffer, GST_MAP_READ)) { GstGLVideoAllocationParams *params; GstGLBaseMemoryAllocator *mem_allocator; GstAllocator *allocator; allocator = GST_ALLOCATOR (gst_gl_memory_allocator_get_default (overlay->context)); mem_allocator = GST_GL_BASE_MEMORY_ALLOCATOR (allocator); gst_gl_composition_overlay_add_transformation (overlay, buf); params = gst_gl_video_allocation_params_new_wrapped_data (overlay->context, NULL, &comp_frame->info, 0, NULL, GST_GL_TEXTURE_TARGET_2D, GST_GL_RGBA, comp_frame->data[0], comp_frame, _video_frame_unmap_and_free); comp_gl_memory = (GstGLMemory *) gst_gl_base_memory_alloc (mem_allocator, (GstGLAllocationParams *) params); gst_gl_allocation_params_free ((GstGLAllocationParams *) params); gst_object_unref (allocator); overlay_buffer = gst_buffer_new (); gst_buffer_append_memory (overlay_buffer, (GstMemory *) comp_gl_memory); if (!gst_video_frame_map (&gl_frame, &comp_frame->info, overlay_buffer, GST_MAP_READ | GST_MAP_GL)) { gst_buffer_unref (overlay_buffer); _video_frame_unmap_and_free (comp_frame); GST_WARNING_OBJECT (overlay, "Cannot upload overlay texture"); return; } gst_memory_ref ((GstMemory *) comp_gl_memory); overlay->gl_memory = comp_gl_memory; overlay->texture_id = comp_gl_memory->tex_id; gst_buffer_unref (overlay_buffer); gst_video_frame_unmap (&gl_frame); GST_DEBUG ("uploaded overlay texture %d", overlay->texture_id); } else { g_slice_free (GstVideoFrame, comp_frame); } }
static void gst_imx_vpu_dec_allocator_init(GstImxVpuDecAllocator *allocator) { GstAllocator *base = GST_ALLOCATOR(allocator); base->mem_type = GST_IMX_VPU_DEC_ALLOCATOR_MEM_TYPE; }
GstV4l2MemoryGroup * gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator, GstAllocator * dmabuf_allocator) { GstV4l2MemoryGroup *group; gint i; g_return_val_if_fail (allocator->memory == V4L2_MEMORY_MMAP, NULL); group = gst_v4l2_allocator_alloc (allocator); if (group == NULL) return NULL; for (i = 0; i < group->n_mem; i++) { GstV4l2Memory *mem; GstMemory *dma_mem; gint dmafd; if (group->mem[i] == NULL) { struct v4l2_exportbuffer expbuf = { 0 }; expbuf.type = allocator->type; expbuf.index = group->buffer.index; expbuf.plane = i; expbuf.flags = O_CLOEXEC | O_RDWR; if (v4l2_ioctl (allocator->video_fd, VIDIOC_EXPBUF, &expbuf) < 0) goto expbuf_failed; GST_LOG_OBJECT (allocator, "exported DMABUF as fd %i plane %d", expbuf.fd, i); group->mem[i] = (GstMemory *) _v4l2mem_new (0, GST_ALLOCATOR (allocator), NULL, group->planes[i].length, 0, 0, group->planes[i].length, i, NULL, expbuf.fd, group); } else { /* Take back the allocator reference */ gst_object_ref (allocator); } g_assert (gst_is_v4l2_memory (group->mem[i])); mem = (GstV4l2Memory *) group->mem[i]; if ((dmafd = dup (mem->dmafd)) < 0) goto dup_failed; dma_mem = gst_dmabuf_allocator_alloc (dmabuf_allocator, dmafd, mem->mem.maxsize); gst_mini_object_set_qdata (GST_MINI_OBJECT (dma_mem), GST_V4L2_MEMORY_QUARK, mem, (GDestroyNotify) gst_memory_unref); group->mem[i] = dma_mem; group->mems_allocated++; } gst_v4l2_allocator_reset_size (allocator, group); return group; expbuf_failed: { GST_ERROR_OBJECT (allocator, "Failed to export DMABUF: %s", g_strerror (errno)); goto cleanup; } dup_failed: { GST_ERROR_OBJECT (allocator, "Failed to dup DMABUF descriptor: %s", g_strerror (errno)); goto cleanup; } cleanup: { _cleanup_failed_alloc (allocator, group); return NULL; } }
static void gst_imx_ipu_allocator_init(GstImxIpuAllocator *allocator) { GstAllocator *base = GST_ALLOCATOR(allocator); base->mem_type = GST_IMX_IPU_ALLOCATOR_MEM_TYPE; }
static GstFlowReturn gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf) { GstShmSink *self = GST_SHM_SINK (bsink); int rv = 0; GstMapInfo map; gboolean need_new_memory = FALSE; GstFlowReturn ret = GST_FLOW_OK; GstMemory *memory = NULL; GstBuffer *sendbuf = NULL; GST_OBJECT_LOCK (self); while (self->wait_for_connection && !self->clients) { g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self)); if (self->unlock) goto 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) goto flushing; } if (gst_buffer_n_memory (buf) > 1) { GST_LOG_OBJECT (self, "Buffer %p has %d GstMemory, we only support a single" " one, need to do a memcpy", buf, gst_buffer_n_memory (buf)); need_new_memory = TRUE; } else { memory = gst_buffer_peek_memory (buf, 0); if (memory->allocator != GST_ALLOCATOR (self->allocator)) { need_new_memory = TRUE; GST_LOG_OBJECT (self, "Memory in buffer %p was not allocated by " "%" GST_PTR_FORMAT ", will memcpy", buf, memory->allocator); } } if (need_new_memory) { if (gst_buffer_get_size (buf) > sp_writer_get_max_buf_size (self->pipe)) { gsize area_size = sp_writer_get_max_buf_size (self->pipe); GST_OBJECT_UNLOCK (self); GST_ELEMENT_ERROR (self, RESOURCE, NO_SPACE_LEFT, ("Shared memory area is too small"), ("Shared memory area of size %" G_GSIZE_FORMAT " is smaller than" "buffer of size %" G_GSIZE_FORMAT, area_size, gst_buffer_get_size (buf))); return GST_FLOW_ERROR; } while ((memory = gst_shm_sink_allocator_alloc_locked (self->allocator, gst_buffer_get_size (buf), &self->params)) == NULL) { g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self)); if (self->unlock) goto flushing; } while (self->wait_for_connection && !self->clients) { g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self)); if (self->unlock) { gst_memory_unref (memory); GST_OBJECT_UNLOCK (self); return GST_FLOW_FLUSHING; } } gst_memory_map (memory, &map, GST_MAP_WRITE); gst_buffer_extract (buf, 0, map.data, map.size); gst_memory_unmap (memory, &map); sendbuf = gst_buffer_new (); gst_buffer_copy_into (sendbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1); gst_buffer_append_memory (sendbuf, memory); } else { sendbuf = gst_buffer_ref (buf); } gst_buffer_map (sendbuf, &map, GST_MAP_READ); /* Make the memory readonly as of now as we've sent it to the other side * We know it's not mapped for writing anywhere as we just mapped it for * reading */ rv = sp_writer_send_buf (self->pipe, (char *) map.data, map.size, sendbuf); gst_buffer_unmap (sendbuf, &map); GST_OBJECT_UNLOCK (self); if (rv == 0) { GST_DEBUG_OBJECT (self, "No clients connected, unreffing buffer"); gst_buffer_unref (sendbuf); } else if (rv == -1) { GST_ELEMENT_ERROR (self, STREAM, FAILED, ("Invalid allocated buffer"), ("The shmpipe library rejects our buffer, this is a bug")); ret = GST_FLOW_ERROR; } /* If we allocated our own memory, then unmap it */ return ret; flushing: GST_OBJECT_UNLOCK (self); return GST_FLOW_FLUSHING; }