static void gst_gl_buffer_pool_finalize (GObject * object) { GstGLBufferPool *pool = GST_GL_BUFFER_POOL_CAST (object); GstGLBufferPoolPrivate *priv = pool->priv; GST_LOG_OBJECT (pool, "finalize GL buffer pool %p", pool); if (priv->caps) gst_caps_unref (priv->caps); G_OBJECT_CLASS (gst_gl_buffer_pool_parent_class)->finalize (object); /* only release the context once all our memory have been deleted */ if (pool->context) { gst_object_unref (pool->context); pool->context = NULL; } if (priv->allocator) { gst_object_unref (priv->allocator); priv->allocator = NULL; } if (priv->gl_params) gst_gl_allocation_params_free ((GstGLAllocationParams *) priv->gl_params); priv->gl_params = NULL; }
static void init (gpointer data) { GstGLContext *context = data; GError *error = NULL; GstVideoInfo v_info; GstGLMemoryAllocator *allocator; GstGLVideoAllocationParams *params; gst_video_info_set_format (&v_info, GST_VIDEO_FORMAT_RGBA, 320, 240); allocator = gst_gl_memory_allocator_get_default (context); params = gst_gl_video_allocation_params_new (context, NULL, &v_info, 0, NULL, GST_GL_TEXTURE_TARGET_2D, GST_GL_RGBA); /* has to be called in the thread that is going to use the framebuffer */ fbo = gst_gl_framebuffer_new_with_default_depth (context, 320, 240); fail_if (fbo == NULL, "failed to create framebuffer object"); gl_tex = (GstGLMemory *) gst_gl_base_memory_alloc ((GstGLBaseMemoryAllocator *) allocator, (GstGLAllocationParams *) params); gl_tex2 = (GstGLMemory *) gst_gl_base_memory_alloc ((GstGLBaseMemoryAllocator *) allocator, (GstGLAllocationParams *) params); gst_object_unref (allocator); gst_gl_allocation_params_free ((GstGLAllocationParams *) params); fail_if (gl_tex == NULL, "failed to create texture"); shader = gst_gl_shader_new_default (context, &error); fail_if (shader == NULL, "failed to create shader object: %s", error->message); shader_attr_position_loc = gst_gl_shader_get_attribute_location (shader, "a_position"); shader_attr_texture_loc = gst_gl_shader_get_attribute_location (shader, "a_texcoord"); }
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 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_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); }