| /* |
| * Copyright (c) 2013-2015, Freescale Semiconductor, Inc. All rights reserved. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public |
| * License along with this library; if not, write to the |
| * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| * Boston, MA 02111-1307, USA. |
| */ |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include "gstallocatorphymem.h" |
| #include "gstphysmemory.h" |
| |
| typedef struct { |
| GstMemory mem; |
| guint8 *vaddr; |
| guint8 *paddr; |
| PhyMemBlock block; |
| } GstMemoryPhy; |
| |
| static int |
| default_copy (GstAllocatorPhyMem *allocator, PhyMemBlock *dst_mem, |
| PhyMemBlock *src_mem, guint offset, guint size) |
| { |
| GST_WARNING ("No default copy implementation for physical memory allocator.\n"); |
| return -1; |
| } |
| |
| static gpointer |
| gst_phymem_map (GstMemory * mem, gsize maxsize, GstMapFlags flags) |
| { |
| GstMemoryPhy *phymem = (GstMemoryPhy*) mem; |
| |
| if (GST_MEMORY_IS_READONLY(mem) && (flags & GST_MAP_WRITE)) { |
| GST_ERROR("memory is read only"); |
| return NULL; |
| } |
| |
| return phymem->vaddr; |
| } |
| |
| static void |
| gst_phymem_unmap (GstMemory * mem) |
| { |
| return; |
| } |
| |
| static GstMemory * |
| gst_phymem_copy (GstMemory * mem, gssize offset, gssize size) |
| { |
| GstAllocatorPhyMemClass *klass; |
| GstMemoryPhy *src_mem = (GstMemoryPhy *)mem; |
| |
| GstMemoryPhy *dst_mem = g_slice_alloc(sizeof(GstMemoryPhy)); |
| if(dst_mem == NULL) { |
| GST_ERROR("Can't allocate for GstMemoryPhy structure.\n"); |
| return NULL; |
| } |
| |
| klass = GST_ALLOCATOR_PHYMEM_CLASS(G_OBJECT_GET_CLASS(mem->allocator)); |
| if(klass == NULL) { |
| GST_ERROR("Can't get class from allocator object.\n"); |
| return NULL; |
| } |
| |
| if(klass->copy_phymem((GstAllocatorPhyMem*)mem->allocator, |
| &dst_mem->block, &src_mem->block, offset, size) < 0) { |
| GST_WARNING ("Copy phymem %d failed.\n", size); |
| return NULL; |
| } |
| |
| GST_DEBUG ("copied phymem, vaddr(%p), paddr(%p), size(%d).\n", |
| dst_mem->block.vaddr, dst_mem->block.paddr, dst_mem->block.size); |
| |
| dst_mem->vaddr = dst_mem->block.vaddr; |
| dst_mem->paddr = dst_mem->block.paddr; |
| |
| gst_memory_init (GST_MEMORY_CAST (dst_mem), |
| mem->mini_object.flags&(~GST_MEMORY_FLAG_READONLY), |
| mem->allocator, NULL, mem->maxsize, mem->align, |
| mem->offset, mem->size); |
| |
| return (GstMemory*)dst_mem; |
| } |
| |
| static GstMemory * |
| gst_phymem_share (GstMemory * mem, gssize offset, gssize size) |
| { |
| GST_ERROR("Not implemented mem_share in gstallocatorphymem.\n"); |
| return NULL; |
| } |
| |
| static gboolean |
| gst_phymem_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset) |
| { |
| return FALSE; |
| } |
| |
| static gpointer |
| gst_phymem_get_phy (GstMemory * mem) |
| { |
| GstMemoryPhy *phymem = (GstMemoryPhy*) mem; |
| |
| return phymem->paddr; |
| } |
| |
| static GstMemory * |
| base_alloc (GstAllocator * allocator, gsize size, |
| GstAllocationParams * params) |
| { |
| GstAllocatorPhyMemClass *klass; |
| GstMemoryPhy *mem; |
| gsize maxsize, aoffset, offset, align, padding; |
| guint8 *data; |
| |
| mem = g_slice_alloc(sizeof(GstMemoryPhy)); |
| if(mem == NULL) { |
| GST_ERROR("Can allocate for GstMemoryPhy structure.\n"); |
| return NULL; |
| } |
| |
| klass = GST_ALLOCATOR_PHYMEM_CLASS(G_OBJECT_GET_CLASS(allocator)); |
| if(klass == NULL) { |
| GST_ERROR("Can't get class from allocator object.\n"); |
| return NULL; |
| } |
| |
| GST_DEBUG ("allocate params, prefix (%d), padding (%d), align (%d), flags (%x).\n", |
| params->prefix, params->padding, params->align, params->flags); |
| |
| maxsize = size + params->prefix + params->padding; |
| mem->block.size = maxsize; |
| if(klass->alloc_phymem((GstAllocatorPhyMem*)allocator, &mem->block) < 0) { |
| GST_ERROR("Allocate phymem %d failed.\n", maxsize); |
| return NULL; |
| } |
| |
| GST_DEBUG ("allocated phymem, vaddr(%p), paddr(%p), size(%d).\n", |
| mem->block.vaddr, mem->block.paddr, mem->block.size); |
| |
| data = mem->block.vaddr; |
| offset = params->prefix; |
| align = params->align; |
| /* do alignment */ |
| if ((aoffset = ((guintptr)data & align))) { |
| aoffset = (align + 1) - aoffset; |
| data += aoffset; |
| maxsize -= aoffset; |
| } |
| mem->vaddr = mem->block.vaddr + aoffset; |
| mem->paddr = mem->block.paddr + aoffset; |
| |
| GST_DEBUG ("aligned vaddr(%p), paddr(%p), size(%d).\n", |
| mem->block.vaddr, mem->block.paddr, mem->block.size); |
| |
| if (offset && (params->flags & GST_MEMORY_FLAG_ZERO_PREFIXED)) |
| memset (data, 0, offset); |
| |
| padding = maxsize - (offset + size); |
| if (padding && (params->flags & GST_MEMORY_FLAG_ZERO_PADDED)) |
| memset (data + offset + size, 0, padding); |
| |
| gst_memory_init (GST_MEMORY_CAST (mem), params->flags, allocator, NULL, maxsize, align, offset, size); |
| |
| return (GstMemory*)mem; |
| } |
| |
| static void |
| base_free (GstAllocator * allocator, GstMemory * mem) |
| { |
| GstAllocatorPhyMemClass *klass; |
| GstMemoryPhy *phymem; |
| |
| klass = GST_ALLOCATOR_PHYMEM_CLASS(G_OBJECT_GET_CLASS(allocator)); |
| if(klass == NULL) { |
| GST_ERROR("Can't get class from allocator object, can't free %p\n", mem); |
| return; |
| } |
| |
| phymem = (GstMemoryPhy*)mem; |
| |
| GST_DEBUG ("free phymem, vaddr(%p), paddr(%p), size(%d).\n", |
| phymem->block.vaddr, phymem->block.paddr, phymem->block.size); |
| |
| klass->free_phymem((GstAllocatorPhyMem*)allocator, &phymem->block); |
| g_slice_free1(sizeof(GstMemoryPhy), mem); |
| |
| return; |
| } |
| |
| static int |
| default_alloc (GstAllocatorPhyMem *allocator, PhyMemBlock *phy_mem) |
| { |
| GST_ERROR ("No default allocating implementation for physical memory allocation.\n"); |
| return -1; |
| } |
| |
| static int |
| default_free (GstAllocatorPhyMem *allocator, PhyMemBlock *phy_mem) |
| { |
| GST_ERROR ("No default free implementation for physical memory allocation.\n"); |
| return -1; |
| } |
| |
| static guintptr |
| gst_allocator_phymem_get_phys_addr (GstPhysMemoryAllocator *allocator, GstMemory *mem) |
| { |
| return gst_phymem_get_phy (mem); |
| } |
| |
| static void gst_allocator_phymem_iface_init(gpointer g_iface) |
| { |
| GstPhysMemoryAllocatorInterface *iface = g_iface; |
| iface->get_phys_addr = gst_allocator_phymem_get_phys_addr; |
| } |
| |
| G_DEFINE_TYPE_WITH_CODE (GstAllocatorPhyMem, gst_allocator_phymem, GST_TYPE_ALLOCATOR, |
| G_IMPLEMENT_INTERFACE(GST_TYPE_PHYS_MEMORY_ALLOCATOR, gst_allocator_phymem_iface_init)); |
| |
| static void |
| gst_allocator_phymem_class_init (GstAllocatorPhyMemClass * klass) |
| { |
| GstAllocatorClass *allocator_class; |
| |
| allocator_class = (GstAllocatorClass *) klass; |
| |
| allocator_class->alloc = base_alloc; |
| allocator_class->free = base_free; |
| klass->alloc_phymem = default_alloc; |
| klass->free_phymem = default_free; |
| klass->copy_phymem = default_copy; |
| } |
| |
| static void |
| gst_allocator_phymem_init (GstAllocatorPhyMem * allocator) |
| { |
| GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator); |
| |
| alloc->mem_map = gst_phymem_map; |
| alloc->mem_unmap = gst_phymem_unmap; |
| alloc->mem_copy = gst_phymem_copy; |
| alloc->mem_share = gst_phymem_share; |
| alloc->mem_is_span = gst_phymem_is_span; |
| } |
| |
| |
| //global functions |
| |
| gboolean |
| gst_buffer_is_phymem (GstBuffer *buffer) |
| { |
| gboolean ret = FALSE; |
| PhyMemBlock * memblk; |
| GstMemory *mem = gst_buffer_get_memory (buffer, 0); |
| if(mem == NULL) { |
| GST_ERROR ("Not get memory from buffer.\n"); |
| return FALSE; |
| } |
| |
| if(GST_IS_ALLOCATOR_PHYMEM(mem->allocator)) { |
| if (NULL == ((GstMemoryPhy*)mem)->block.paddr) { |
| GST_WARNING("physical address in memory block is invalid"); |
| ret = FALSE; |
| } else { |
| ret = TRUE; |
| } |
| } |
| |
| gst_memory_unref (mem); |
| |
| return ret; |
| } |
| |
| PhyMemBlock * |
| gst_buffer_query_phymem_block (GstBuffer *buffer) |
| { |
| GstMemory *mem; |
| GstMemoryPhy *memphy; |
| PhyMemBlock *memblk; |
| |
| mem = gst_buffer_get_memory (buffer, 0); |
| if(mem == NULL) { |
| GST_ERROR ("Not get memory from buffer.\n"); |
| return NULL; |
| } |
| |
| if(!GST_IS_ALLOCATOR_PHYMEM(mem->allocator)) { |
| gst_memory_unref (mem); |
| return NULL; |
| } |
| |
| memphy = (GstMemoryPhy*) mem; |
| memblk = &memphy->block; |
| |
| gst_memory_unref (mem); |
| |
| return memblk; |
| } |
| |
| PhyMemBlock * |
| gst_memory_query_phymem_block (GstMemory *mem) |
| { |
| GstMemoryPhy *memphy; |
| PhyMemBlock *memblk; |
| |
| if (!mem) |
| return NULL; |
| |
| if (!GST_IS_ALLOCATOR_PHYMEM(mem->allocator)) |
| return NULL; |
| |
| memphy = (GstMemoryPhy*) mem; |
| memblk = &memphy->block; |
| |
| return memblk; |
| } |
| |