/* gstreamermm - a C++ wrapper for gstreamer
 *
 * Copyright 2008-2016 The gstreamermm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <gst/gst.h>
#include <gstreamermm/miniobject.h>
#include <gstreamermm/mapinfo.h>

_DEFS(gstreamermm,gst)

namespace Gst
{

_WRAP_ENUM(MemoryFlags, GstMemoryFlags)

class Allocator;

/**
 * GstMemory is a lightweight refcounted object that wraps a region of memory.
 * They are typically used to manage the data of a Gst::Buffer.
 *
 * A GstMemory object has an allocated region of memory of maxsize. The maximum
 * size does not change during the lifetime of the memory object. The memory
 * also has an offset and size property that specifies the valid range of memory
 * in the allocated region.
 *
 * Memory is usually created by allocators with a Gst::Allocator::alloc()
 * method call.
 *
 * New memory can be created with Gst::Memory::create() that wraps the memory
 * allocated elsewhere.
 *
 * The size of the memory can be retrieved and changed with get_sizes()
 * and resize() respectively.
 *
 * Getting access to the data of the memory is performed with map().
 * The call will return a pointer to offset bytes into the region of memory.
 * After the memory access is completed, unmap() should be called.
 *
 * Memory can be copied with copy(), which will return a writable
 * copy. share() will create a new memory block that shares the
 * memory with an existing memory block at a custom offset and with a custom
 * size.
 *
 * Memory can be efficiently merged when is_span() returns %TRUE.
 *
 * Last reviewed on 2016-06-05 (1.8.0)
 */
class Memory : public MiniObject
{
  _CLASS_OPAQUE_REFCOUNTED(Memory, GstMemory, NONE, gst_memory_ref, gst_memory_unref)
  _IGNORE(gst_memory_ref, gst_memory_unref)

public:

  /*
   * Allocate a new memory block that wraps the given @a data.
   *
   * @param flags: Gst::MemoryFlags.
   * @param data Data to wrap.
   * @param maxsize Allocated size of @a data.
   * @param offset Offset in @data.
   * @param size Size of valid data.
   *
   * @returns a new #Gst::Memory.
   */
  static Glib::RefPtr<Memory> create(Gst::MemoryFlags flags, gpointer data, gsize maxsize, gsize offset, gsize size);

  /** Get the maximum size allocated.
   */
  _MEMBER_GET(maxsize, maxsize, gsize, gsize)

  /** Get the alignment of the memory.
   */
  _MEMBER_GET(align, align, gsize, gsize)

  /** Get the offset where valid data starts.
   */
  _MEMBER_GET(offset, offset, gsize, gsize)

  /** Get the size of valid data.
   */
  _MEMBER_GET(size, size, gsize, gsize)

  /** Get parent memory block.
   */
  _MEMBER_GET_GOBJECT(parent, parent, Gst::Memory, GstMemory*)

  /** Get the Gst::Allocator.
   */
  _MEMBER_GET_GOBJECT(allocator, allocator, Gst::Allocator, GstAllocator*)

  _WRAP_METHOD(bool is_type(const Glib::ustring& mem_type) const, gst_memory_is_type)
  _WRAP_METHOD(Glib::RefPtr<Gst::Memory> share(gssize offset, gssize size), gst_memory_share)
  _WRAP_METHOD(void resize(gssize offset, gsize size), gst_memory_resize)
  _WRAP_METHOD(bool is_span(const Glib::RefPtr<Gst::Memory>& mem2, gsize& offset), gst_memory_is_span)
  _WRAP_METHOD(bool map(Gst::MapInfo& info, Gst::MapFlags flags), gst_memory_map)
  _WRAP_METHOD(void unmap(Gst::MapInfo& info), gst_memory_unmap)
  _WRAP_METHOD(Glib::RefPtr<Gst::Memory> copy(gssize offset, gssize size), gst_memory_copy)
  _WRAP_METHOD(void init(Gst::MemoryFlags flags, const Glib::RefPtr<Gst::Allocator>& allocator, const Glib::RefPtr<Gst::Memory>& parent, gsize maxsize, gsize align, gsize offset, gsize size), gst_memory_init)
  _WRAP_METHOD(gsize get_sizes(gsize& offset, gsize& maxsize), gst_memory_get_sizes)

  /** Create a Gst::Memory object that is mapped with @a flags. If @a mem is mappable
   * with @a flags, this function returns the mapped @a mem directly. Otherwise a
   * mapped copy of @a mem is returned.
   *
   * @param info Pointer for info.
   * @param flags Mapping flags.
   *
   * @return a Gst::Memory object mapped.
   */
  Glib::RefPtr<Gst::Memory> make_mapped(Gst::MapInfo& info, Gst::MapFlags flags);
  _IGNORE(gst_memory_make_mapped)

};

}//namespace Gst
