static GstVulkanMemory * _vk_mem_new (GstAllocator * allocator, GstMemory * parent, GstVulkanDevice * device, guint32 memory_type_index, GstAllocationParams * params, gsize size, VkMemoryPropertyFlags mem_props_flags, gpointer user_data, GDestroyNotify notify) { GstVulkanMemory *mem = g_new0 (GstVulkanMemory, 1); GError *error = NULL; VkResult err; _vk_mem_init (mem, allocator, parent, device, memory_type_index, params, size, mem_props_flags, user_data, notify); err = vkAllocateMemory (device->device, &mem->alloc_info, NULL, &mem->mem_ptr); if (gst_vulkan_error_to_g_error (err, &error, "vkAllocMemory") < 0) { GST_CAT_ERROR (GST_CAT_VULKAN_MEMORY, "Failed to allocate device memory %s", error->message); gst_memory_unref ((GstMemory *) mem); g_clear_error (&error); return NULL; } return mem; }
static VkBool32 _gst_vk_debug_callback (VkDebugReportFlagsEXT msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg, void *pUserData) { if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { GST_CAT_ERROR (GST_VULKAN_DEBUG_CAT, "[%s] Code %d : %s", pLayerPrefix, msgCode, pMsg); } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { GST_CAT_WARNING (GST_VULKAN_DEBUG_CAT, "[%s] Code %d : %s", pLayerPrefix, msgCode, pMsg); } else if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) { GST_CAT_LOG (GST_VULKAN_DEBUG_CAT, "[%s] Code %d : %s", pLayerPrefix, msgCode, pMsg); } else if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) { GST_CAT_FIXME (GST_VULKAN_DEBUG_CAT, "[%s] Code %d : %s", pLayerPrefix, msgCode, pMsg); } else if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) { GST_CAT_TRACE (GST_VULKAN_DEBUG_CAT, "[%s] Code %d : %s", pLayerPrefix, msgCode, pMsg); } else { return FALSE; } /* * false indicates that layer should not bail-out of an * API call that had validation failures. This may mean that the * app dies inside the driver due to invalid parameter(s). * That's what would happen without validation layers, so we'll * keep that behavior here. */ return FALSE; }
static gpointer _gl_mem_map_gpu_access (GstGLMemoryPBO * gl_mem, GstMapInfo * info, gsize size) { gpointer data = &gl_mem->mem.tex_id; if ((info->flags & GST_MAP_READ) == GST_MAP_READ) { if (gl_mem->pbo && CONTEXT_SUPPORTS_PBO_UPLOAD (gl_mem->mem.mem.context)) { GstMapInfo pbo_info; /* data -> pbo */ if (!gst_memory_map (GST_MEMORY_CAST (gl_mem->pbo), &pbo_info, GST_MAP_READ | GST_MAP_GL)) { GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Failed to map pbo"); return NULL; } /* pbo -> texture */ _upload_pbo_memory (gl_mem, info, gl_mem->pbo, &pbo_info); gst_memory_unmap (GST_MEMORY_CAST (gl_mem->pbo), &pbo_info); } else { GstGLMemoryAllocatorClass *alloc_class; alloc_class = GST_GL_MEMORY_ALLOCATOR_CLASS (parent_class); data = alloc_class->map ((GstGLBaseMemory *) gl_mem, info, size); } } return data; }
static GstGLMemoryEGL * _gl_mem_egl_alloc (GstGLBaseMemoryAllocator * allocator, GstGLVideoAllocationParams * params) { guint alloc_flags = params->parent.alloc_flags; GstGLMemoryEGL *mem; g_return_val_if_fail (alloc_flags & GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_VIDEO, NULL); g_return_val_if_fail ((alloc_flags & GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_WRAP_SYSMEM) == 0, NULL); if (alloc_flags & GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_WRAP_GPU_HANDLE) { g_return_val_if_fail (GST_IS_EGL_IMAGE (params->parent.gl_handle), NULL); } mem = g_new0 (GstGLMemoryEGL, 1); if (alloc_flags & GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_WRAP_GPU_HANDLE) { if (params->target != GST_GL_TEXTURE_TARGET_2D) { g_free (mem); GST_CAT_ERROR (GST_CAT_GL_MEMORY, "GstGLMemoryEGL only supports wrapping " "2D textures"); return NULL; } mem->image = gst_egl_image_ref (params->parent.gl_handle); } gst_gl_memory_init (GST_GL_MEMORY_CAST (mem), GST_ALLOCATOR_CAST (allocator), NULL, params->parent.context, params->target, params->tex_type, params->parent.alloc_params, params->v_info, params->plane, params->valign, params->parent.user_data, params->parent.notify); return mem; }
static GstMemory * _gl_mem_copy (GstGLMemoryPBO * src, gssize offset, gssize size) { GstAllocationParams params = { 0, GST_MEMORY_CAST (src)->align, 0, 0 }; GstGLBaseMemoryAllocator *base_mem_allocator; GstAllocator *allocator; GstMemory *dest = NULL; allocator = GST_MEMORY_CAST (src)->allocator; base_mem_allocator = (GstGLBaseMemoryAllocator *) allocator; if (src->mem.tex_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES) { GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Cannot copy External OES textures"); return NULL; } /* If not doing a full copy, then copy to sysmem, the 2D represention of the * texture would become wrong */ if (offset > 0 || size < GST_MEMORY_CAST (src)->size) { return base_mem_allocator->fallback_mem_copy (GST_MEMORY_CAST (src), offset, size); } dest = (GstMemory *) _gl_mem_new (allocator, NULL, src->mem.mem.context, src->mem.tex_target, ¶ms, &src->mem.info, src->mem.plane, &src->mem.valign, NULL, NULL); if (GST_MEMORY_FLAG_IS_SET (src, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD)) { if (!gst_gl_base_memory_memcpy ((GstGLBaseMemory *) src, (GstGLBaseMemory *) dest, offset, size)) { GST_CAT_WARNING (GST_CAT_GL_MEMORY, "Could not copy GL Memory"); gst_memory_unref (GST_MEMORY_CAST (dest)); return NULL; } } else { GstMapInfo dinfo; if (!gst_memory_map (GST_MEMORY_CAST (dest), &dinfo, GST_MAP_WRITE | GST_MAP_GL)) { GST_CAT_WARNING (GST_CAT_GL_MEMORY, "Failed not map destination " "for writing"); gst_memory_unref (GST_MEMORY_CAST (dest)); return NULL; } if (!gst_gl_memory_copy_into ((GstGLMemory *) src, ((GstGLMemory *) dest)->tex_id, src->mem.tex_target, src->mem.tex_type, src->mem.tex_width, GL_MEM_HEIGHT (src))) { GST_CAT_WARNING (GST_CAT_GL_MEMORY, "Could not copy GL Memory"); gst_memory_unmap (GST_MEMORY_CAST (dest), &dinfo); gst_memory_unref (GST_MEMORY_CAST (dest)); return NULL; } gst_memory_unmap (GST_MEMORY_CAST (dest), &dinfo); } return dest; }
static GstStateChangeReturn gst_dshowaudiosrc_change_state (GstElement * element, GstStateChange transition) { HRESULT hres = S_FALSE; GstDshowAudioSrc *src = GST_DSHOWAUDIOSRC (element); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: break; case GST_STATE_CHANGE_READY_TO_PAUSED: break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: if (src->media_filter) hres = IMediaFilter_Run (src->media_filter, 0); if (hres != S_OK) { GST_CAT_ERROR (dshowaudiosrc_debug, "Can't RUN the directshow capture graph (error=%d)", hres); src->is_running = FALSE; return GST_STATE_CHANGE_FAILURE; } else { src->is_running = TRUE; } break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED: if (src->media_filter) hres = IMediaFilter_Stop (src->media_filter); if (hres != S_OK) { GST_CAT_ERROR (dshowaudiosrc_debug, "Can't STOP the directshow capture graph (error=%d)", hres); return GST_STATE_CHANGE_FAILURE; } src->is_running = FALSE; break; case GST_STATE_CHANGE_PAUSED_TO_READY: break; case GST_STATE_CHANGE_READY_TO_NULL: break; default: break; } return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); }
static gboolean got_gl_error (const char *wtf) { GLuint error = GL_NO_ERROR; if ((error = glGetError ()) != GL_NO_ERROR) { GST_CAT_ERROR (GST_CAT_DEFAULT, "GL ERROR: %s returned 0x%04x", wtf, error); return TRUE; } return FALSE; }
static gpointer _vk_mem_map_full (GstVulkanMemory * mem, GstMapInfo * info, gsize size) { gpointer data; VkResult err; GError *error = NULL; if ((mem->properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) { GST_CAT_ERROR (GST_CAT_VULKAN_MEMORY, "Cannot map host-invisible memory"); return NULL; } err = vkMapMemory (mem->device->device, mem->mem_ptr, mem->vk_offset, size, 0, &data); if (gst_vulkan_error_to_g_error (err, &error, "vkMapMemory") < 0) { GST_CAT_ERROR (GST_CAT_VULKAN_MEMORY, "Failed to map device memory %s", error->message); g_clear_error (&error); return NULL; } return data; }
static void _mem_create_gl (GstGLContext * context, struct create_data *transfer) { GstGLBaseBufferAllocatorClass *alloc_class; GError *error = NULL; alloc_class = GST_GL_BASE_BUFFER_ALLOCATOR_GET_CLASS (transfer->mem->mem.allocator); g_return_if_fail (alloc_class->create != NULL); if ((transfer->result = alloc_class->create (transfer->mem, &error))) return; g_assert (error != NULL); GST_CAT_ERROR (GST_CAT_GL_BASE_BUFFER, "Failed to create GL buffer: %s", error->message); }
static gpointer _pbo_download_transfer (GstGLMemoryPBO * gl_mem, GstMapInfo * info, gsize size) { GstMapInfo *pbo_info; gl_mem->pbo->target = GL_PIXEL_PACK_BUFFER; /* texture -> pbo */ if (info->flags & GST_MAP_READ && GST_MEMORY_FLAG_IS_SET (gl_mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)) { GstMapInfo info; GST_CAT_TRACE (GST_CAT_GL_MEMORY, "attempting download of texture %u " "using pbo %u", gl_mem->mem.tex_id, gl_mem->pbo->id); if (!gst_memory_map (GST_MEMORY_CAST (gl_mem->pbo), &info, GST_MAP_WRITE | GST_MAP_GL)) { GST_CAT_WARNING (GST_CAT_GL_MEMORY, "Failed to write to PBO"); return NULL; } if (!_read_pixels_to_pbo (gl_mem)) { gst_memory_unmap (GST_MEMORY_CAST (gl_mem->pbo), &info); return NULL; } gst_memory_unmap (GST_MEMORY_CAST (gl_mem->pbo), &info); } pbo_info = g_new0 (GstMapInfo, 1); /* pbo -> data */ /* get a cpu accessible mapping from the pbo */ if (!gst_memory_map (GST_MEMORY_CAST (gl_mem->pbo), pbo_info, info->flags)) { GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Failed to map pbo"); g_free (pbo_info); return NULL; } info->user_data[0] = pbo_info; return pbo_info->data; }
static gpointer _gl_mem_map (GstGLMemoryPBO * gl_mem, GstMapInfo * info, gsize maxsize) { gpointer data; if ((info->flags & GST_MAP_GL) == GST_MAP_GL) { if (gl_mem->mem.tex_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES) return &gl_mem->mem.tex_id; data = _gl_mem_map_gpu_access (gl_mem, info, maxsize); } else { /* not GL */ if (gl_mem->mem.tex_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES) { GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Cannot map External OES textures"); return NULL; } data = _gl_mem_map_cpu_access (gl_mem, info, maxsize); } return data; }
/** * gst_memory_map: * @mem: a #GstMemory * @info: (out): pointer for info * @flags: mapping flags * * Fill @info with the pointer and sizes of the memory in @mem that can be * accessed according to @flags. * * This function can return %FALSE for various reasons: * - the memory backed by @mem is not accessible with the given @flags. * - the memory was already mapped with a different mapping. * * @info and its contents remain valid for as long as @mem is valid and * until gst_memory_unmap() is called. * * For each gst_memory_map() call, a corresponding gst_memory_unmap() call * should be done. * * Returns: %TRUE if the map operation was successful. */ gboolean gst_memory_map (GstMemory * mem, GstMapInfo * info, GstMapFlags flags) { g_return_val_if_fail (mem != NULL, FALSE); g_return_val_if_fail (info != NULL, FALSE); if (!gst_memory_lock (mem, (GstLockFlags) flags)) goto lock_failed; info->data = mem->allocator->mem_map (mem, mem->maxsize, flags); if (G_UNLIKELY (info->data == NULL)) goto error; info->memory = mem; info->flags = flags; info->size = mem->size; info->maxsize = mem->maxsize - mem->offset; info->data = info->data + mem->offset; return TRUE; /* ERRORS */ lock_failed: { GST_CAT_DEBUG (GST_CAT_MEMORY, "mem %p: lock %d failed", mem, flags); memset (info, 0, sizeof (GstMapInfo)); return FALSE; } error: { /* something went wrong, restore the orginal state again */ GST_CAT_ERROR (GST_CAT_MEMORY, "mem %p: subclass map failed", mem); gst_memory_unlock (mem, (GstLockFlags) flags); memset (info, 0, sizeof (GstMapInfo)); return FALSE; } }
void gst_gl_base_buffer_init (GstGLBaseBuffer * mem, GstAllocator * allocator, GstMemory * parent, GstGLContext * context, GstAllocationParams * params, gsize size) { gsize align = gst_memory_alignment, offset = 0, maxsize = size; GstMemoryFlags flags = 0; struct create_data data; if (params) { flags = params->flags; align |= params->align; offset = params->prefix; maxsize += params->prefix + params->padding + align; } gst_memory_init (GST_MEMORY_CAST (mem), flags, allocator, parent, maxsize, align, offset, size); mem->context = gst_object_ref (context); mem->data = NULL; mem->alloc_data = NULL; g_mutex_init (&mem->lock); data.mem = mem; gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _mem_create_gl, &data); if (!data.result) { GST_CAT_ERROR (GST_CAT_GL_BASE_BUFFER, "Could not create GL buffer with context:%p", context); } GST_CAT_DEBUG (GST_CAT_GL_BASE_BUFFER, "new GL buffer memory:%p size:%" G_GSIZE_FORMAT, mem, maxsize); }
static gboolean _read_pixels_to_pbo (GstGLMemoryPBO * gl_mem) { if (!gl_mem->pbo || !CONTEXT_SUPPORTS_PBO_DOWNLOAD (gl_mem->mem.mem.context) || gl_mem->mem.tex_type == GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE || gl_mem->mem.tex_type == GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA) /* unsupported */ return FALSE; if (GST_MEMORY_FLAG_IS_SET (gl_mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)) { /* copy texture data into into the pbo and map that */ gsize plane_start; GstMapInfo pbo_info; plane_start = gst_gl_get_plane_start (&gl_mem->mem.info, &gl_mem->mem.valign, gl_mem->mem.plane) + GST_MEMORY_CAST (gl_mem)->offset; gl_mem->pbo->target = GL_PIXEL_PACK_BUFFER; if (!gst_memory_map (GST_MEMORY_CAST (gl_mem->pbo), &pbo_info, GST_MAP_WRITE | GST_MAP_GL)) { GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Failed to map pbo for writing"); return FALSE; } if (!gst_gl_memory_read_pixels ((GstGLMemory *) gl_mem, (gpointer) plane_start)) { gst_memory_unmap (GST_MEMORY_CAST (gl_mem->pbo), &pbo_info); return FALSE; } gst_memory_unmap (GST_MEMORY_CAST (gl_mem->pbo), &pbo_info); } return TRUE; }
static void _mem_create_gl (GstGLContext * context, struct create_data *transfer) { GstGLBaseMemoryAllocatorClass *alloc_class; GError *error = NULL; GST_CAT_TRACE (GST_CAT_GL_BASE_MEMORY, "Create memory %p", transfer->mem); alloc_class = GST_GL_BASE_MEMORY_ALLOCATOR_GET_CLASS (transfer->mem->mem.allocator); g_return_if_fail (alloc_class->create != NULL); transfer->mem->query = gst_gl_query_new (context, GST_GL_QUERY_TIME_ELAPSED); if ((transfer->result = alloc_class->create (transfer->mem, &error))) return; g_assert (error != NULL); GST_CAT_ERROR (GST_CAT_GL_BASE_MEMORY, "Failed to create GL buffer: %s", error->message); g_clear_error (&error); }
static gboolean gst_dshowaudiosrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec) { HRESULT hres; IGstDshowInterface *srcinterface = NULL; IPin *input_pin = NULL; GstDshowAudioSrc *src = GST_DSHOWAUDIOSRC (asrc); /* search the negociated caps in our caps list to get its index and the corresponding mediatype */ if (gst_caps_is_subset (spec->caps, src->caps)) { guint i = 0; gint res = -1; for (; i < gst_caps_get_size (src->caps) && res == -1; i++) { GstCaps *capstmp = gst_caps_copy_nth (src->caps, i); if (gst_caps_is_subset (spec->caps, capstmp)) { res = i; } gst_caps_unref (capstmp); } if (res != -1 && src->pins_mediatypes) { /*get the corresponding media type and build the dshow graph */ GstCapturePinMediaType *pin_mediatype = NULL; GList *type = g_list_nth (src->pins_mediatypes, res); if (type) { pin_mediatype = (GstCapturePinMediaType *) type->data; hres = IBaseFilter_QueryInterface (src->dshow_fakesink, &IID_IGstDshowInterface, (void **) &srcinterface); if (hres != S_OK || !srcinterface) { GST_CAT_ERROR (dshowaudiosrc_debug, "Can't get IGstDshowInterface interface from our dshow fakesink filter (error=%d)", hres); goto error; } IGstDshowInterface_gst_set_media_type (srcinterface, pin_mediatype->mediatype); IGstDshowInterface_gst_set_buffer_callback (srcinterface, (byte *) gst_dshowaudiosrc_push_buffer, (byte *) src); if (srcinterface) { IGstDshowInterface_Release (srcinterface); } gst_dshow_get_pin_from_filter (src->dshow_fakesink, PINDIR_INPUT, &input_pin); if (!input_pin) { GST_CAT_ERROR (dshowaudiosrc_debug, "Can't get input pin from our directshow fakesink filter"); goto error; } hres = IFilterGraph_ConnectDirect (src->filter_graph, pin_mediatype->capture_pin, input_pin, NULL); IPin_Release (input_pin); if (hres != S_OK) { GST_CAT_ERROR (dshowaudiosrc_debug, "Can't connect capture filter with fakesink filter (error=%d)", hres); goto error; } spec->segsize = spec->rate * spec->channels; spec->segtotal = 1; } } } return TRUE; error: if (srcinterface) { IGstDshowInterface_Release (srcinterface); } return FALSE; }
static gboolean gst_dshowaudiosrc_open (GstAudioSrc * asrc) { HRESULT hres = S_FALSE; GstDshowAudioSrc *src = GST_DSHOWAUDIOSRC (asrc); hres = CoCreateInstance (&CLSID_FilterGraph, NULL, CLSCTX_INPROC, &IID_IFilterGraph, (LPVOID *) & src->filter_graph); if (hres != S_OK || !src->filter_graph) { GST_CAT_ERROR (dshowaudiosrc_debug, "Can't create an instance of the directshow graph manager (error=%d)", hres); goto error; } hres = IFilterGraph_QueryInterface (src->filter_graph, &IID_IMediaFilter, (void **) &src->media_filter); if (hres != S_OK || !src->media_filter) { GST_CAT_ERROR (dshowaudiosrc_debug, "Can't get IMediacontrol interface from the graph manager (error=%d)", hres); goto error; } hres = CoCreateInstance (&CLSID_DshowFakeSink, NULL, CLSCTX_INPROC, &IID_IBaseFilter, (LPVOID *) & src->dshow_fakesink); if (hres != S_OK || !src->dshow_fakesink) { GST_CAT_ERROR (dshowaudiosrc_debug, "Can't create an instance of the directshow fakesink (error=%d)", hres); goto error; } hres = IFilterGraph_AddFilter (src->filter_graph, src->audio_cap_filter, L"capture"); if (hres != S_OK) { GST_CAT_ERROR (dshowaudiosrc_debug, "Can't add the directshow capture filter to the graph (error=%d)", hres); goto error; } hres = IFilterGraph_AddFilter (src->filter_graph, src->dshow_fakesink, L"fakesink"); if (hres != S_OK) { GST_CAT_ERROR (dshowaudiosrc_debug, "Can't add our fakesink filter to the graph (error=%d)", hres); goto error; } return TRUE; error: if (src->dshow_fakesink) { IBaseFilter_Release (src->dshow_fakesink); src->dshow_fakesink = NULL; } if (src->media_filter) { IMediaFilter_Release (src->media_filter); src->media_filter = NULL; } if (src->filter_graph) { IFilterGraph_Release (src->filter_graph); src->filter_graph = NULL; } return FALSE; }
static GstCaps * gst_dshowaudiosrc_get_caps (GstBaseSrc * basesrc) { HRESULT hres = S_OK; IBindCtx *lpbc = NULL; IMoniker *audiom = NULL; DWORD dwEaten; GstDshowAudioSrc *src = GST_DSHOWAUDIOSRC (basesrc); gunichar2 *unidevice = NULL; if (src->device) { g_free (src->device); src->device = NULL; } src->device = gst_dshow_getdevice_from_devicename (&CLSID_AudioInputDeviceCategory, &src->device_name); if (!src->device) { GST_CAT_ERROR (dshowaudiosrc_debug, "No audio device found."); return NULL; } unidevice = g_utf8_to_utf16 (src->device, strlen (src->device), NULL, NULL, NULL); if (!src->audio_cap_filter) { hres = CreateBindCtx (0, &lpbc); if (SUCCEEDED (hres)) { hres = MkParseDisplayName (lpbc, unidevice, &dwEaten, &audiom); if (SUCCEEDED (hres)) { hres = IMoniker_BindToObject (audiom, lpbc, NULL, &IID_IBaseFilter, &src->audio_cap_filter); IMoniker_Release (audiom); } IBindCtx_Release (lpbc); } } if (src->audio_cap_filter && !src->caps) { /* get the capture pins supported types */ IPin *capture_pin = NULL; IEnumPins *enumpins = NULL; HRESULT hres; hres = IBaseFilter_EnumPins (src->audio_cap_filter, &enumpins); if (SUCCEEDED (hres)) { while (IEnumPins_Next (enumpins, 1, &capture_pin, NULL) == S_OK) { IKsPropertySet *pKs = NULL; hres = IPin_QueryInterface (capture_pin, &IID_IKsPropertySet, (void **) &pKs); if (SUCCEEDED (hres) && pKs) { DWORD cbReturned; GUID pin_category; RPC_STATUS rpcstatus; hres = IKsPropertySet_Get (pKs, &ROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, NULL, 0, &pin_category, sizeof (GUID), &cbReturned); /* we only want capture pins */ if (UuidCompare (&pin_category, &PIN_CATEGORY_CAPTURE, &rpcstatus) == 0) { IAMStreamConfig *streamcaps = NULL; if (SUCCEEDED (IPin_QueryInterface (capture_pin, &IID_IAMStreamConfig, (void **) &streamcaps))) { src->caps = gst_dshowaudiosrc_getcaps_from_streamcaps (src, capture_pin, streamcaps); IAMStreamConfig_Release (streamcaps); } } IKsPropertySet_Release (pKs); } IPin_Release (capture_pin); } IEnumPins_Release (enumpins); } } if (unidevice) { g_free (unidevice); } if (src->caps) { return gst_caps_ref (src->caps); } return NULL; }
static GValueArray * gst_dshowaudiosrc_get_device_name_values (GstDshowAudioSrc * src) { GValueArray *array = g_value_array_new (0); GValue value = { 0 }; ICreateDevEnum *devices_enum = NULL; IEnumMoniker *moniker_enum = NULL; IMoniker *moniker = NULL; HRESULT hres = S_FALSE; ULONG fetched; g_value_init (&value, G_TYPE_STRING); hres = CoCreateInstance (&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, &IID_ICreateDevEnum, (void **) &devices_enum); if (hres != S_OK) { GST_CAT_ERROR (dshowaudiosrc_debug, "Can't create an instance of the system device enumerator (error=%d)", hres); array = NULL; goto clean; } hres = ICreateDevEnum_CreateClassEnumerator (devices_enum, &CLSID_AudioInputDeviceCategory, &moniker_enum, 0); if (hres != S_OK || !moniker_enum) { GST_CAT_ERROR (dshowaudiosrc_debug, "Can't get enumeration of audio devices (error=%d)", hres); array = NULL; goto clean; } IEnumMoniker_Reset (moniker_enum); while (hres = IEnumMoniker_Next (moniker_enum, 1, &moniker, &fetched), hres == S_OK) { IPropertyBag *property_bag = NULL; hres = IMoniker_BindToStorage (moniker, NULL, NULL, &IID_IPropertyBag, (void **) &property_bag); if (SUCCEEDED (hres) && property_bag) { VARIANT varFriendlyName; VariantInit (&varFriendlyName); hres = IPropertyBag_Read (property_bag, L"FriendlyName", &varFriendlyName, NULL); if (hres == S_OK && varFriendlyName.bstrVal) { gchar *friendly_name = g_utf16_to_utf8 ((const gunichar2 *) varFriendlyName.bstrVal, wcslen (varFriendlyName.bstrVal), NULL, NULL, NULL); g_value_set_string (&value, friendly_name); g_value_array_append (array, &value); g_value_unset (&value); g_free (friendly_name); SysFreeString (varFriendlyName.bstrVal); } IPropertyBag_Release (property_bag); } IMoniker_Release (moniker); } clean: if (moniker_enum) { IEnumMoniker_Release (moniker_enum); } if (devices_enum) { ICreateDevEnum_Release (devices_enum); } return array; }
/** * gst_gl_base_memory_init: * @mem: the #GstGLBaseMemory to initialize * @allocator: the #GstAllocator to initialize with * @parent: (allow-none): the parent #GstMemory to initialize with * @context: the #GstGLContext to initialize with * @params: (allow-none): the @GstAllocationParams to initialize with * @size: the number of bytes to be allocated * @user_data: (allow-none): user data to call @notify with * @notify: (allow-none): a #GDestroyNotify * * Initializes @mem with the required parameters */ void gst_gl_base_memory_init (GstGLBaseMemory * mem, GstAllocator * allocator, GstMemory * parent, GstGLContext * context, GstAllocationParams * params, gsize size, gpointer user_data, GDestroyNotify notify) { gsize align = gst_memory_alignment, offset = 0, maxsize; GstMemoryFlags flags = 0; struct create_data data; /* A note on sizes. * gl_mem->alloc_size: the size to allocate when we control the allocation. * Size of the unaligned allocation. * mem->maxsize: the size that is used by GstMemory for mapping, to map the * entire memory. The size of the aligned allocation * mem->size: represents the size of the valid data. Can be reduced with * gst_memory_resize() * * It holds that: * mem->size + mem->offset <= mem->maxsize * and * mem->maxsize + alignment offset <= gl_mem->alloc_size * * We need to add the alignment mask to the allocated size in order to have * the freedom to align the gl_mem->data pointer correctly which may be offset * by at most align bytes in the alloc_data pointer. * * maxsize is not suitable for this as it is used by GstMemory as the size * to map with. */ mem->alloc_size = maxsize = size; if (params) { flags = params->flags; align |= params->align; offset = params->prefix; maxsize += params->prefix + params->padding; /* deals with any alignment */ mem->alloc_size = maxsize + align; } gst_memory_init (GST_MEMORY_CAST (mem), flags, allocator, parent, maxsize, align, offset, size); mem->context = gst_object_ref (context); mem->notify = notify; mem->user_data = user_data; g_mutex_init (&mem->lock); data.mem = mem; gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _mem_create_gl, &data); if (!data.result) { GST_CAT_ERROR (GST_CAT_GL_BASE_MEMORY, "Could not create GL buffer with context:%p", context); } GST_CAT_DEBUG (GST_CAT_GL_BASE_MEMORY, "new GL buffer memory:%p size:%" G_GSIZE_FORMAT, mem, maxsize); }
static void _gl_mem_copy_thread (GstGLContext * context, gpointer data) { const GstGLFuncs *gl; GstGLMemoryPBOCopyParams *copy_params; GstGLMemoryPBO *src; guint tex_id; guint out_tex_target; GLuint fboId; gsize out_width, out_height, out_stride; GLuint out_gl_format, out_gl_type; GLuint in_gl_format, in_gl_type; gsize in_size, out_size; copy_params = (GstGLMemoryPBOCopyParams *) data; src = copy_params->src; tex_id = copy_params->tex_id; out_tex_target = gst_gl_texture_target_to_gl (copy_params->tex_target); out_width = copy_params->out_width; out_height = copy_params->out_height; out_stride = copy_params->out_stride; gl = context->gl_vtable; out_gl_format = gst_gl_format_from_gl_texture_type (copy_params->out_format); out_gl_type = GL_UNSIGNED_BYTE; if (copy_params->out_format == GST_VIDEO_GL_TEXTURE_TYPE_RGB16) out_gl_type = GL_UNSIGNED_SHORT_5_6_5; in_gl_format = gst_gl_format_from_gl_texture_type (src->mem.tex_type); in_gl_type = GL_UNSIGNED_BYTE; if (src->mem.tex_type == GST_VIDEO_GL_TEXTURE_TYPE_RGB16) in_gl_type = GL_UNSIGNED_SHORT_5_6_5; if (!gl->GenFramebuffers) { gst_gl_context_set_error (context, "Context, EXT_framebuffer_object not supported"); goto error; } in_size = GL_MEM_HEIGHT (src) * GL_MEM_STRIDE (src); out_size = out_height * out_stride; if (copy_params->respecify) { if (in_size != out_size) { GST_ERROR ("Cannot copy between textures with backing data of different" "sizes. input %" G_GSIZE_FORMAT " output %" G_GSIZE_FORMAT, in_size, out_size); goto error; } } if (!tex_id) { guint internal_format; guint out_gl_type; out_gl_type = GL_UNSIGNED_BYTE; if (copy_params->out_format == GST_VIDEO_GL_TEXTURE_TYPE_RGB16) out_gl_type = GL_UNSIGNED_SHORT_5_6_5; internal_format = gst_gl_sized_gl_format_from_gl_format_type (context, out_gl_format, out_gl_type); tex_id = _new_texture (context, out_tex_target, internal_format, out_gl_format, out_gl_type, copy_params->out_width, copy_params->out_height); } if (!tex_id) { GST_WARNING ("Could not create GL texture with context:%p", context); } GST_LOG ("copying memory %p, tex %u into texture %i", src, src->mem.tex_id, tex_id); /* FIXME: try and avoid creating and destroying fbo's every copy... */ /* create a framebuffer object */ gl->GenFramebuffers (1, &fboId); gl->BindFramebuffer (GL_FRAMEBUFFER, fboId); gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, gst_gl_texture_target_to_gl (src->mem.tex_target), src->mem.tex_id, 0); // if (!gst_gl_context_check_framebuffer_status (src->mem.mem.context)) // goto fbo_error; gl->BindTexture (out_tex_target, tex_id); if (copy_params->respecify) { GstMapInfo pbo_info; if (!gl->GenBuffers || !src->pbo) { gst_gl_context_set_error (context, "Cannot reinterpret texture contents " "without pixel buffer objects"); gl->BindTexture (out_tex_target, 0); goto fbo_error; } if (gst_gl_context_get_gl_api (context) & GST_GL_API_GLES2 && (in_gl_format != GL_RGBA || in_gl_type != GL_UNSIGNED_BYTE)) { gst_gl_context_set_error (context, "Cannot copy non RGBA/UNSIGNED_BYTE " "textures on GLES2"); gl->BindTexture (out_tex_target, 0); goto fbo_error; } GST_TRACE ("copying texture data with size of %u*%u*%u", gst_gl_format_type_n_bytes (in_gl_format, in_gl_type), src->mem.tex_width, GL_MEM_HEIGHT (src)); /* copy tex */ _read_pixels_to_pbo (src); src->pbo->target = GL_PIXEL_UNPACK_BUFFER; if (!gst_memory_map (GST_MEMORY_CAST (src->pbo), &pbo_info, GST_MAP_READ | GST_MAP_GL)) { GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Failed to map pbo for reading"); goto fbo_error; } gl->TexSubImage2D (out_tex_target, 0, 0, 0, out_width, out_height, out_gl_format, out_gl_type, 0); gst_memory_unmap (GST_MEMORY_CAST (src->pbo), &pbo_info); } else { /* different sizes */ gst_gl_memory_copy_teximage (GST_GL_MEMORY_CAST (src), tex_id, copy_params->tex_target, copy_params->out_format, out_width, out_height); } gl->BindTexture (out_tex_target, 0); gl->BindFramebuffer (GL_FRAMEBUFFER, 0); gl->DeleteFramebuffers (1, &fboId); copy_params->tex_id = tex_id; copy_params->result = TRUE; return; /* ERRORS */ fbo_error: { gl->DeleteFramebuffers (1, &fboId); copy_params->tex_id = 0; copy_params->result = FALSE; return; } error: { copy_params->result = FALSE; return; } }
gint main (gint argc, gchar * argv[]) { gst_init (&argc, &argv); GST_DEBUG_CATEGORY_INIT (cat_default, "GST_Check_default", 0, "default category for this test"); GST_DEBUG_CATEGORY_INIT (cat2, "GST_Check_2", 0, "second category for this test"); #ifndef GST_DISABLE_GST_DEBUG g_assert (gst_debug_remove_log_function (gst_debug_log_default) == 1); #endif gst_debug_add_log_function (check_message, NULL); count = 0; GST_ERROR ("This is an error."); ++count; GST_WARNING ("This is a warning."); ++count; GST_INFO ("This is an info message."); ++count; GST_DEBUG ("This is a debug message."); ++count; GST_LOG ("This is a log message."); ++count; GST_CAT_ERROR (cat2, "This is an error with category."); ++count; GST_CAT_WARNING (cat2, "This is a warning with category."); ++count; GST_CAT_INFO (cat2, "This is an info message with category."); ++count; GST_CAT_DEBUG (cat2, "This is a debug message with category."); ++count; GST_CAT_LOG (cat2, "This is a log message with category."); count = -1; pipeline = gst_element_factory_make ("pipeline", "testelement"); count = 10; GST_ERROR_OBJECT (pipeline, "This is an error with object."); ++count; GST_WARNING_OBJECT (pipeline, "This is a warning with object."); ++count; GST_INFO_OBJECT (pipeline, "This is an info message with object."); ++count; GST_DEBUG_OBJECT (pipeline, "This is a debug message with object."); ++count; GST_LOG_OBJECT (pipeline, "This is a log message with object."); ++count; GST_CAT_ERROR_OBJECT (cat2, pipeline, "This is an error with category and object."); ++count; GST_CAT_WARNING_OBJECT (cat2, pipeline, "This is a warning with category and object."); ++count; GST_CAT_INFO_OBJECT (cat2, pipeline, "This is an info message with category and object."); ++count; GST_CAT_DEBUG_OBJECT (cat2, pipeline, "This is a debug message with category and object."); ++count; GST_CAT_LOG_OBJECT (cat2, pipeline, "This is a log message with category and object."); count = -1; #ifndef GST_DISABLE_GST_DEBUG g_assert (gst_debug_remove_log_function (check_message) == 1); #endif return 0; }
gboolean gst_egl_image_memory_setup_buffer (GstGLContext * ctx, GstVideoInfo * info, GstBuffer * buffer) { gint i = 0; gint stride[3]; gsize offset[3]; GstMemory *mem[3] = { NULL, NULL, NULL }; guint n_mem = 0; GstMemoryFlags flags = 0; EGLImageKHR image = EGL_NO_IMAGE_KHR; EGLClientBuffer client_buffer_tex[3] = { 0, 0, 0 }; GstVideoGLTextureType texture_types[] = { 0, 0, 0, 0 }; GstEGLImageAllocator *allocator = gst_egl_image_allocator_obtain (); GstGLContextEGL *context = GST_GL_CONTEXT_EGL (ctx); g_return_val_if_fail (ctx, FALSE); g_return_val_if_fail (info, FALSE); g_return_val_if_fail (buffer, FALSE); g_return_val_if_fail (gst_gl_context_check_feature (ctx, "EGL_KHR_image_base"), FALSE); memset (stride, 0, sizeof (stride)); memset (offset, 0, sizeof (offset)); flags |= GST_MEMORY_FLAG_NOT_MAPPABLE; flags |= GST_MEMORY_FLAG_NO_SHARE; switch (GST_VIDEO_INFO_FORMAT (info)) { case GST_VIDEO_FORMAT_RGB: case GST_VIDEO_FORMAT_BGR: case GST_VIDEO_FORMAT_RGB16: case GST_VIDEO_FORMAT_RGBA: case GST_VIDEO_FORMAT_BGRA: case GST_VIDEO_FORMAT_ARGB: case GST_VIDEO_FORMAT_ABGR: case GST_VIDEO_FORMAT_RGBx: case GST_VIDEO_FORMAT_BGRx: case GST_VIDEO_FORMAT_xRGB: case GST_VIDEO_FORMAT_xBGR: case GST_VIDEO_FORMAT_AYUV: { gsize size = 0; switch (GST_VIDEO_INFO_FORMAT (info)) { case GST_VIDEO_FORMAT_RGB: case GST_VIDEO_FORMAT_BGR: case GST_VIDEO_FORMAT_RGB16: { texture_types[0] = GST_VIDEO_GL_TEXTURE_TYPE_RGB; break; } case GST_VIDEO_FORMAT_RGBA: case GST_VIDEO_FORMAT_BGRA: case GST_VIDEO_FORMAT_ARGB: case GST_VIDEO_FORMAT_ABGR: case GST_VIDEO_FORMAT_RGBx: case GST_VIDEO_FORMAT_BGRx: case GST_VIDEO_FORMAT_xRGB: case GST_VIDEO_FORMAT_xBGR: case GST_VIDEO_FORMAT_AYUV: { texture_types[0] = GST_VIDEO_GL_TEXTURE_TYPE_RGBA; break; } default: g_assert_not_reached (); break; } #if 0 mem[0] = gst_egl_image_allocator_alloc (allocator, context, texture_types[0], GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info), size); if (mem[0]) { stride[0] = size / GST_VIDEO_INFO_HEIGHT (info); n_mem = 1; GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE); } else #endif { gst_gl_generate_texture_full (GST_GL_CONTEXT (context), info, 0, stride, offset, &size, (GLuint *) & client_buffer_tex[0]); image = context->eglCreateImage (context->egl_display, context->egl_context, EGL_GL_TEXTURE_2D_KHR, client_buffer_tex[0], NULL); if (eglGetError () != EGL_SUCCESS) goto mem_error; mem[0] = gst_egl_image_allocator_wrap (allocator, context, image, texture_types[0], flags, size, client_buffer_tex[0], (GstEGLImageDestroyNotify) gst_egl_image_memory_del_gl_texture); n_mem = 1; } break; } case GST_VIDEO_FORMAT_NV12: case GST_VIDEO_FORMAT_NV21: { gsize size[2]; texture_types[0] = GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE; texture_types[1] = GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA; #if 0 mem[0] = gst_egl_image_allocator_alloc (allocator, context, texture_types[0], GST_VIDEO_INFO_COMP_WIDTH (info, 0), GST_VIDEO_INFO_COMP_HEIGHT (info, 0), size[0]); mem[1] = gst_egl_image_allocator_alloc (allocator, context, texture_types[1], GST_VIDEO_INFO_COMP_WIDTH (info, 1), GST_VIDEO_INFO_COMP_HEIGHT (info, 1), size[1]); if (mem[0] && mem[1]) { stride[0] = size[0] / GST_VIDEO_INFO_HEIGHT (info); offset[1] = size[0]; stride[1] = size[1] / GST_VIDEO_INFO_HEIGHT (info); n_mem = 2; GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE); GST_MINI_OBJECT_FLAG_SET (mem[1], GST_MEMORY_FLAG_NO_SHARE); } else { if (mem[0]) gst_memory_unref (mem[0]); if (mem[1]) gst_memory_unref (mem[1]); mem[0] = mem[1] = NULL; } #endif { for (i = 0; i < 2; i++) { gst_gl_generate_texture_full (GST_GL_CONTEXT (context), info, 0, stride, offset, size, (GLuint *) & client_buffer_tex[i]); image = context->eglCreateImage (context->egl_display, context->egl_context, EGL_GL_TEXTURE_2D_KHR, client_buffer_tex[i], NULL); if (eglGetError () != EGL_SUCCESS) goto mem_error; mem[i] = gst_egl_image_allocator_wrap (allocator, context, image, texture_types[i], flags, size[i], client_buffer_tex[i], (GstEGLImageDestroyNotify) gst_egl_image_memory_del_gl_texture); } n_mem = 2; } break; } case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: case GST_VIDEO_FORMAT_Y444: case GST_VIDEO_FORMAT_Y42B: case GST_VIDEO_FORMAT_Y41B: { gsize size[3]; texture_types[0] = GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE; texture_types[1] = GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE; texture_types[2] = GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE; #if 0 mem[0] = gst_egl_image_allocator_alloc (allocator, context, texture_types[0], GST_VIDEO_INFO_COMP_WIDTH (info, 0), GST_VIDEO_INFO_COMP_HEIGHT (info, 0), size[0]); mem[1] = gst_egl_image_allocator_alloc (allocator, context, texture_types[1], GST_VIDEO_INFO_COMP_WIDTH (info, 1), GST_VIDEO_INFO_COMP_HEIGHT (info, 1), size[1]); mem[2] = gst_egl_image_allocator_alloc (allocator, context, texture_types[2], GST_VIDEO_INFO_COMP_WIDTH (info, 2), GST_VIDEO_INFO_COMP_HEIGHT (info, 2), size[2]); if (mem[0] && mem[1] && mem[2]) { stride[0] = size[0] / GST_VIDEO_INFO_HEIGHT (info); offset[1] = size[0]; stride[1] = size[1] / GST_VIDEO_INFO_HEIGHT (info); offset[2] = size[1]; stride[2] = size[2] / GST_VIDEO_INFO_HEIGHT (info); n_mem = 3; GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE); GST_MINI_OBJECT_FLAG_SET (mem[1], GST_MEMORY_FLAG_NO_SHARE); GST_MINI_OBJECT_FLAG_SET (mem[2], GST_MEMORY_FLAG_NO_SHARE); } else { if (mem[0]) gst_memory_unref (mem[0]); if (mem[1]) gst_memory_unref (mem[1]); if (mem[2]) gst_memory_unref (mem[2]); mem[0] = mem[1] = mem[2] = NULL; } #endif { for (i = 0; i < 3; i++) { gst_gl_generate_texture_full (GST_GL_CONTEXT (context), info, i, stride, offset, size, (GLuint *) & client_buffer_tex[i]); image = context->eglCreateImage (context->egl_display, context->egl_context, EGL_GL_TEXTURE_2D_KHR, client_buffer_tex[i], NULL); if (eglGetError () != EGL_SUCCESS) goto mem_error; mem[i] = gst_egl_image_allocator_wrap (allocator, context, image, texture_types[i], flags, size[i], client_buffer_tex[i], (GstEGLImageDestroyNotify) gst_egl_image_memory_del_gl_texture); } n_mem = 3; } break; } default: g_assert_not_reached (); break; } gst_buffer_add_video_meta_full (buffer, 0, GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info), GST_VIDEO_INFO_N_PLANES (info), offset, stride); gst_buffer_add_video_gl_texture_upload_meta (buffer, gst_egl_image_memory_get_orientation (mem[0]), n_mem, texture_types, gst_eglimage_to_gl_texture_upload_meta, NULL, NULL, NULL); for (i = 0; i < n_mem; i++) gst_buffer_append_memory (buffer, mem[i]); return TRUE; mem_error: { GST_CAT_ERROR (GST_CAT_DEFAULT, "Failed to create EGLImage"); for (i = 0; i < 3; i++) { if (client_buffer_tex[i]) gst_gl_context_del_texture (ctx, (GLuint *) & client_buffer_tex[i]); if (mem[i]) gst_memory_unref (mem[i]); } return FALSE; } }
static inline void _calculate_unpack_length (GstGLMemory * gl_mem) { guint n_gl_bytes; gl_mem->tex_scaling[0] = 1.0f; gl_mem->tex_scaling[1] = 1.0f; gl_mem->unpack_length = 1; gl_mem->tex_width = GL_MEM_WIDTH (gl_mem); n_gl_bytes = _gl_texture_type_n_bytes (gl_mem->tex_type); if (n_gl_bytes == 0) { GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Unsupported texture type %d", gl_mem->tex_type); return; } if (USING_OPENGL (gl_mem->context) || USING_GLES3 (gl_mem->context)) { gl_mem->unpack_length = GL_MEM_STRIDE (gl_mem) / n_gl_bytes; } else if (USING_GLES2 (gl_mem->context)) { guint j = 8; while (j >= n_gl_bytes) { /* GST_ROUND_UP_j(GL_MEM_WIDTH (gl_mem) * n_gl_bytes) */ guint round_up_j = ((GL_MEM_WIDTH (gl_mem) * n_gl_bytes) + j - 1) & ~(j - 1); if (round_up_j == GL_MEM_STRIDE (gl_mem)) { GST_CAT_LOG (GST_CAT_GL_MEMORY, "Found alignment of %u based on width " "(with plane width:%u, plane stride:%u and pixel stride:%u. " "RU%u(%u*%u) = %u)", j, GL_MEM_WIDTH (gl_mem), GL_MEM_STRIDE (gl_mem), n_gl_bytes, j, GL_MEM_WIDTH (gl_mem), n_gl_bytes, round_up_j); gl_mem->unpack_length = j; break; } j >>= 1; } if (j < n_gl_bytes) { /* Failed to find a suitable alignment, try based on plane_stride and * scale in the shader. Useful for alignments that are greater than 8. */ j = 8; while (j >= n_gl_bytes) { /* GST_ROUND_UP_j((GL_MEM_STRIDE (gl_mem)) */ guint round_up_j = ((GL_MEM_STRIDE (gl_mem)) + j - 1) & ~(j - 1); if (round_up_j == (GL_MEM_STRIDE (gl_mem))) { GST_CAT_LOG (GST_CAT_GL_MEMORY, "Found alignment of %u based on " "stride (with plane stride:%u and pixel stride:%u. " "RU%u(%u) = %u)", j, GL_MEM_STRIDE (gl_mem), n_gl_bytes, j, GL_MEM_STRIDE (gl_mem), round_up_j); gl_mem->unpack_length = j; gl_mem->tex_scaling[0] = (gfloat) (GL_MEM_WIDTH (gl_mem) * n_gl_bytes) / (gfloat) GL_MEM_STRIDE (gl_mem); gl_mem->tex_width = GL_MEM_STRIDE (gl_mem) / n_gl_bytes; break; } j >>= 1; } if (j < n_gl_bytes) { GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Failed to find matching alignment. Image may " "look corrupted. plane width:%u, plane stride:%u and pixel " "stride:%u", GL_MEM_WIDTH (gl_mem), GL_MEM_STRIDE (gl_mem), n_gl_bytes); } }
static GstMemory * _gl_mem_copy (GstGLMemoryEGL * src, gssize offset, gssize size) { GST_CAT_ERROR (GST_CAT_GL_MEMORY, "GstGLMemoryEGL does not support copy"); return NULL; }