static gboolean _gl_mem_create (GstGLMemoryPBO * gl_mem, GError ** error) { GstGLContext *context = gl_mem->mem.mem.context; GstGLBaseMemoryAllocatorClass *alloc_class; alloc_class = GST_GL_BASE_MEMORY_ALLOCATOR_CLASS (parent_class); if (!alloc_class->create ((GstGLBaseMemory *) gl_mem, error)) return FALSE; if (CONTEXT_SUPPORTS_PBO_DOWNLOAD (context) || CONTEXT_SUPPORTS_PBO_UPLOAD (context)) { GstAllocationParams alloc_params = { 0, GST_MEMORY_CAST (gl_mem)->align, 0, 0 }; GstGLBaseMemoryAllocator *buf_allocator; GstGLBufferAllocationParams *params; buf_allocator = GST_GL_BASE_MEMORY_ALLOCATOR (gst_allocator_find (GST_GL_BUFFER_ALLOCATOR_NAME)); params = gst_gl_buffer_allocation_params_new (context, GST_MEMORY_CAST (gl_mem)->size, &alloc_params, GL_PIXEL_UNPACK_BUFFER, GL_STREAM_DRAW); /* FIXME: lazy init this for resource constrained platforms * Will need to fix pbo detection based on the existence of the mem.id then */ gl_mem->pbo = (GstGLBuffer *) gst_gl_base_memory_alloc (buf_allocator, (GstGLAllocationParams *) params); gst_gl_allocation_params_free ((GstGLAllocationParams *) params); gst_object_unref (buf_allocator); GST_CAT_LOG (GST_CAT_GL_MEMORY, "generated pbo %u", gl_mem->pbo->id); } return TRUE; }
static void test_transfer_allocator (const gchar * allocator_name) { GstAllocator *gl_allocator; GstGLBaseMemoryAllocator *base_mem_alloc; GstVideoInfo v_info; GstMemory *mem, *mem2, *mem3; GstMapInfo map_info; GstGLVideoAllocationParams *params; gl_allocator = gst_allocator_find (allocator_name); fail_if (gl_allocator == NULL); base_mem_alloc = GST_GL_BASE_MEMORY_ALLOCATOR (gl_allocator); gst_video_info_set_format (&v_info, GST_VIDEO_FORMAT_RGBA, 1, 1); params = gst_gl_video_allocation_params_new (context, NULL, &v_info, 0, NULL, GST_GL_TEXTURE_TARGET_2D, GST_VIDEO_GL_TEXTURE_TYPE_RGBA); /* texture creation */ mem = (GstMemory *) gst_gl_base_memory_alloc (base_mem_alloc, (GstGLAllocationParams *) params); gst_gl_allocation_params_free ((GstGLAllocationParams *) params); fail_unless (!GST_MEMORY_FLAG_IS_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD)); fail_unless (!GST_MEMORY_FLAG_IS_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)); /* test wrapping raw data */ params = gst_gl_video_allocation_params_new_wrapped_data (context, NULL, &v_info, 0, NULL, GST_GL_TEXTURE_TARGET_2D, GST_VIDEO_GL_TEXTURE_TYPE_RGBA, rgba_pixel, NULL, NULL); mem2 = (GstMemory *) gst_gl_base_memory_alloc (base_mem_alloc, (GstGLAllocationParams *) params); gst_gl_allocation_params_free ((GstGLAllocationParams *) params); fail_if (mem == NULL); fail_unless (GST_MEMORY_FLAG_IS_SET (mem2, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD)); fail_unless (!GST_MEMORY_FLAG_IS_SET (mem2, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)); /* wrapped texture creation */ params = gst_gl_video_allocation_params_new_wrapped_texture (context, NULL, &v_info, 0, NULL, GST_GL_TEXTURE_TARGET_2D, GST_VIDEO_GL_TEXTURE_TYPE_RGBA, ((GstGLMemory *) mem)->tex_id, NULL, NULL); mem3 = (GstMemory *) gst_gl_base_memory_alloc (base_mem_alloc, (GstGLAllocationParams *) params); gst_gl_allocation_params_free ((GstGLAllocationParams *) params); fail_unless (!GST_MEMORY_FLAG_IS_SET (mem3, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD)); fail_unless (GST_MEMORY_FLAG_IS_SET (mem3, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)); /* check data/flags are correct */ fail_unless (gst_memory_map (mem2, &map_info, GST_MAP_READ)); fail_unless (GST_MEMORY_FLAG_IS_SET (mem2, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD)); fail_unless (!GST_MEMORY_FLAG_IS_SET (mem2, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)); fail_unless (memcmp (map_info.data, rgba_pixel, G_N_ELEMENTS (rgba_pixel)) == 0, "0x%02x%02x%02x%02x != 0x%02x%02x%02x%02x", map_info.data[0], map_info.data[1], map_info.data[2], map_info.data[3], (guint8) rgba_pixel[0], (guint8) rgba_pixel[1], (guint8) rgba_pixel[2], (guint8) rgba_pixel[3]); gst_memory_unmap (mem2, &map_info); fail_unless (GST_MEMORY_FLAG_IS_SET (mem2, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD)); fail_unless (!GST_MEMORY_FLAG_IS_SET (mem2, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)); fail_unless (gst_memory_map (mem2, &map_info, GST_MAP_READ | GST_MAP_GL)); fail_unless (!GST_MEMORY_FLAG_IS_SET (mem2, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD)); fail_unless (!GST_MEMORY_FLAG_IS_SET (mem2, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)); /* test texture copy */ fail_unless (gst_gl_memory_copy_into ((GstGLMemory *) mem2, ((GstGLMemory *) mem)->tex_id, GST_GL_TEXTURE_TARGET_2D, GST_VIDEO_GL_TEXTURE_TYPE_RGBA, 1, 1)); GST_MINI_OBJECT_FLAG_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD); fail_unless (!GST_MEMORY_FLAG_IS_SET (mem2, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD)); fail_unless (!GST_MEMORY_FLAG_IS_SET (mem2, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)); fail_unless (!GST_MEMORY_FLAG_IS_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD)); fail_unless (GST_MEMORY_FLAG_IS_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)); gst_memory_unmap (mem2, &map_info); /* test download of copied texture */ fail_unless (gst_memory_map (mem, &map_info, GST_MAP_READ)); fail_unless (memcmp (map_info.data, rgba_pixel, G_N_ELEMENTS (rgba_pixel)) == 0, "0x%02x%02x%02x%02x != 0x%02x%02x%02x%02x", (guint8) map_info.data[0], (guint8) map_info.data[1], (guint8) map_info.data[2], (guint8) map_info.data[3], (guint8) rgba_pixel[0], (guint8) rgba_pixel[1], (guint8) rgba_pixel[2], (guint8) rgba_pixel[3]); gst_memory_unmap (mem, &map_info); /* test download of wrapped copied texture */ fail_unless (gst_memory_map (mem3, &map_info, GST_MAP_READ)); fail_unless (!GST_MEMORY_FLAG_IS_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD)); fail_unless (!GST_MEMORY_FLAG_IS_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)); fail_unless (memcmp (map_info.data, rgba_pixel, G_N_ELEMENTS (rgba_pixel)) == 0, "0x%02x%02x%02x%02x != 0x%02x%02x%02x%02x", (guint8) map_info.data[0], (guint8) map_info.data[1], (guint8) map_info.data[2], (guint8) map_info.data[3], (guint8) rgba_pixel[0], (guint8) rgba_pixel[1], (guint8) rgba_pixel[2], (guint8) rgba_pixel[3]); gst_memory_unmap (mem3, &map_info); /* test upload flag */ fail_unless (gst_memory_map (mem3, &map_info, GST_MAP_WRITE)); gst_memory_unmap (mem3, &map_info); fail_unless (GST_MEMORY_FLAG_IS_SET (mem3, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD)); fail_unless (!GST_MEMORY_FLAG_IS_SET (mem3, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)); /* test download flag */ fail_unless (gst_memory_map (mem3, &map_info, GST_MAP_WRITE | GST_MAP_GL)); gst_memory_unmap (mem3, &map_info); fail_unless (!GST_MEMORY_FLAG_IS_SET (mem3, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD)); fail_unless (GST_MEMORY_FLAG_IS_SET (mem3, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)); gst_memory_unref (mem); gst_memory_unref (mem2); gst_memory_unref (mem3); gst_object_unref (gl_allocator); }
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 check_conversion (TestFrame * frames, guint size) { GstGLBaseMemoryAllocator *base_mem_alloc; gint i, j, k, l; gint ref_count = 0; base_mem_alloc = GST_GL_BASE_MEMORY_ALLOCATOR (gst_allocator_find (GST_GL_MEMORY_ALLOCATOR_NAME)); for (i = 0; i < size; i++) { GstBuffer *inbuf; GstVideoInfo in_info; gint in_width = frames[i].width; gint in_height = frames[i].height; GstVideoFormat in_v_format = frames[i].v_format; GstVideoFrame in_frame; GstCaps *in_caps; gst_video_info_set_format (&in_info, in_v_format, in_width, in_height); in_caps = gst_video_info_to_caps (&in_info); gst_caps_set_features (in_caps, 0, gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY)); /* create GL buffer */ inbuf = gst_buffer_new (); for (j = 0; j < GST_VIDEO_INFO_N_PLANES (&in_info); j++) { GstVideoGLTextureType tex_type = gst_gl_texture_type_from_format (context, GST_VIDEO_INFO_FORMAT (&in_info), j); GstGLVideoAllocationParams *params; GstGLBaseMemory *mem; ref_count++; params = gst_gl_video_allocation_params_new_wrapped_data (context, NULL, &in_info, j, NULL, GST_GL_TEXTURE_TARGET_2D, tex_type, frames[i].data[j], &ref_count, _frame_unref); mem = gst_gl_base_memory_alloc (base_mem_alloc, (GstGLAllocationParams *) params); gst_buffer_append_memory (inbuf, GST_MEMORY_CAST (mem)); gst_gl_allocation_params_free ((GstGLAllocationParams *) params); } fail_unless (gst_video_frame_map (&in_frame, &in_info, inbuf, GST_MAP_READ)); /* sanity check that the correct values were wrapped */ for (j = 0; j < GST_VIDEO_INFO_N_PLANES (&in_info); j++) { for (k = 0; k < _video_info_plane_size (&in_info, j); k++) { if (frames[i].data[j][k] != IGNORE_MAGIC) fail_unless (((gchar *) in_frame.data[j])[k] == frames[i].data[j][k]); } } for (j = 0; j < size; j++) { GstBuffer *outbuf; GstVideoInfo out_info; gint out_width = frames[j].width; gint out_height = frames[j].height; GstVideoFormat out_v_format = frames[j].v_format; gchar *out_data[GST_VIDEO_MAX_PLANES] = { 0 }; GstVideoFrame out_frame; GstCaps *out_caps; gst_video_info_set_format (&out_info, out_v_format, out_width, out_height); out_caps = gst_video_info_to_caps (&out_info); gst_caps_set_features (out_caps, 0, gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY)); for (k = 0; k < GST_VIDEO_INFO_N_PLANES (&out_info); k++) { out_data[k] = frames[j].data[k]; } gst_gl_color_convert_set_caps (convert, in_caps, out_caps); /* convert the data */ outbuf = gst_gl_color_convert_perform (convert, inbuf); if (outbuf == NULL) { const gchar *in_str = gst_video_format_to_string (in_v_format); const gchar *out_str = gst_video_format_to_string (out_v_format); GST_WARNING ("failed to convert from %s to %s", in_str, out_str); } fail_unless (gst_video_frame_map (&out_frame, &out_info, outbuf, GST_MAP_READ)); /* check that the converted values are correct */ for (k = 0; k < GST_VIDEO_INFO_N_PLANES (&out_info); k++) { for (l = 0; l < _video_info_plane_size (&out_info, k); l++) { gchar out_pixel = ((gchar *) out_frame.data[k])[l]; if (out_data[k][l] != IGNORE_MAGIC && out_pixel != IGNORE_MAGIC) fail_unless (out_pixel == out_data[k][l]); /* FIXME: check alpha clobbering */ } } gst_caps_unref (out_caps); gst_video_frame_unmap (&out_frame); gst_buffer_unref (outbuf); } gst_caps_unref (in_caps); gst_video_frame_unmap (&in_frame); gst_buffer_unref (inbuf); fail_unless_equals_int (ref_count, 0); } gst_object_unref (base_mem_alloc); }