GStreamer如何优化内存管理策略?

2026-05-29 08:454阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1647个文字,预计阅读时间需要7分钟。

GStreamer如何优化内存管理策略?

GstMemory:管理小块实际虚拟内存GstBuffer:对象,element、plugin、application间最小数据单元,内部包含GstMemory、时间信息及其他信息GstMeta:附加在GstBuffer上


  • GstMemory:管理一小块实际的虚拟内存
  • GstBuffer:一个对象,是element、plugin、application互相信息交互的最小数据单位,内部包含GstMemory、时间信息和一些其他信息。
  • GstMeta:附加在GstBuffer上,用来提供一些描述内存的额外信息。
  • GstBufferPool:buffer池,但是只能分配尺寸固定的buffer。

GstMemory:

/**
* GstMemory:
* @mini_object: parent structure
* @allocator: pointer to the #GstAllocator
* @parent: parent memory block
* @maxsize: the maximum size allocated
* @align: the alignment of the memory
* @offset: the offset where valid data starts
* @size: the size of valid data
*
* Base structure for memory implementations. Custom memory will put this structure
* as the first member of their structure.
*/
struct _GstMemory {
GstMiniObject mini_object;

GstAllocator *allocator;

GstMemory *parent;
gsize maxsize;
gsize align;
gsize offset;
gsize size;
};

GstMemory由GstAllocator创建。

GstAllocator:

/**
* GstAllocator:
* @mem_map: the implementation of the GstMemoryMapFunction
* @mem_unmap: the implementation of the GstMemoryUnmapFunction
* @mem_copy: the implementation of the GstMemoryCopyFunction
* @mem_share: the implementation of the GstMemoryShareFunction
* @mem_is_span: the implementation of the GstMemoryIsSpanFunction
* @mem_map_full: the implementation of the GstMemoryMapFullFunction.
* Will be used instead of @mem_map if present. (Since: 1.6)
* @mem_unmap_full: the implementation of the GstMemoryUnmapFullFunction.
* Will be used instead of @mem_unmap if present. (Since: 1.6)
*
* The #GstAllocator is used to create new memory.
*/
struct _GstAllocator
{
GstObject object;

const gchar *mem_type;

/*< public >*/
GstMemoryMapFunction mem_map;
GstMemoryUnmapFunction mem_unmap;

GstMemoryCopyFunction mem_copy;
GstMemoryShareFunction mem_share;
GstMemoryIsSpanFunction mem_is_span;

GstMemoryMapFullFunction mem_map_full;
GstMemoryUnmapFullFunction mem_unmap_full;

/*< private >*/
gpointer _gst_reserved[GST_PADDING - 2];

GstAllocatorPrivate *priv;
};

内存分配器,是一个接口层,如果自行管理内存分配,可以自己实现这个接口。

内存分配和使用:

使用 gst_allocator_alloc 分配内存,此函数返回的是一个 GstMemory 指针,GstMemory内的数据必须通过 gst_memory_map 保护才可以访问,然后通过gst_memory_unmap 释放保护后别人才可以访问,类似于加锁解锁。

[...]

GstMemory *mem;
GstMapInfo info;
gint i;

/* allocate 100 bytes */
mem = gst_allocator_alloc (NULL, 100, NULL);

/* get access to the memory in write mode */
gst_memory_map (mem, &info, GST_MAP_WRITE);

/* fill with pattern */
for (i = 0; i < info.size; i++)
info.data[i] = i;

/* release memory */
gst_memory_unmap (mem, &info);

[...]

GstBuffer:

  • GstBuffer内部包含了n个GstMemory,同时也包含了一些meta data:
  • dts 、pts:用来进行同步。
  • duration:buffer内数据总时长,不是整个流的总时长。
  • offset :buffer存视频时,表示当前buffer内第一帧数据在整个流中是第多少个帧;buffer存音频时,???
  • offset_end:buffer存视频时,表示当前buffer内最后一帧数据在整个流中是第多少个帧;buffer存音频时,???
/**
* GstBuffer:
* @mini_object: the parent structure
* @pool: pointer to the pool owner of the buffer
* @pts: presentation timestamp of the buffer, can be #GST_CLOCK_TIME_NONE when the
* pts is not known or relevant. The pts contains the timestamp when the
* media should be presented to the user.
* @dts: decoding timestamp of the buffer, can be #GST_CLOCK_TIME_NONE when the
* dts is not known or relevant. The dts contains the timestamp when the
* media should be processed.
* @duration: duration in time of the buffer data, can be #GST_CLOCK_TIME_NONE
* when the duration is not known or relevant.
* @offset: a media specific offset for the buffer data.
* For video frames, this is the frame number of this buffer.
* For audio samples, this is the offset of the first sample in this buffer.
* For file data or compressed data this is the byte offset of the first
* byte in this buffer.
* @offset_end: the last offset contained in this buffer. It has the same
* format as @offset.
*
* The structure of a #GstBuffer. Use the associated macros to access the public
* variables.
*/
struct _GstBuffer {
GstMiniObject mini_object;

/*< public >*/ /* with COW */
GstBufferPool *pool;

/* timestamp */
GstClockTime pts;
GstClockTime dts;
GstClockTime duration;

/* media specific offset */
guint64 offset;
guint64 offset_end;
};

默认情况下GstBuffer是不可写的,需要先通过gst_buffer_make_writable函数处理,然后才可以修改里面的内容,比如dts、pts、duration、offset等等。

三种创建GstBuffer的方法:

  • gst_buffer_new 创建GstBuffer 对象,但是创建的对象不包含 GstMemory,需要手动创建GstMemory再进行绑定;
  • gst_buffer_new_allocate 同时创建GstBuffer 和 指定数量的GstMemory,然后还会自动完成绑定动作;
  • gst_buffer_new_wrapped_full 为现有GstMemory创建一个GstBuffer。
  • [...]
    GstBuffer *buffer;
    GstMemory *mem;
    GstMapInfo info;

    /* make empty buffer */
    buffer = gst_buffer_new ();

    /* make memory holding 100 bytes */
    mem = gst_allocator_alloc (NULL, 100, NULL);

    /* add the buffer */
    gst_buffer_append_memory (buffer, mem);

    [...]

    /* get WRITE access to the memory and fill with 0xff */
    gst_buffer_map (buffer, &info, GST_MAP_WRITE);
    memset (info.data, 0xff, info.size);
    gst_buffer_unmap (buffer, &info);

    [...]

    /* free the buffer */
    gst_buffer_unref (buffer);

    [...]

    GstMeta:

    /**
    * GstMeta:
    * @flags: extra flags for the metadata
    * @info: pointer to the #GstMetaInfo
    *
    * Base structure for metadata. Custom metadata will put this structure
    * as the first member of their structure.
    */
    struct _GstMeta {
    GstMetaFlags flags;
    const GstMetaInfo *info;
    };

    GstMeta可以随意地附加到一个GstBuffer中。

    #include <gst/video/gstvideometa.h>

    [...]
    GstVideoCropMeta *meta; //GstMeta的一个子类

    /* buffer points to a video frame, add some cropping metadata */
    meta = gst_buffer_add_video_crop_meta (buffer);

    /* configure the cropping metadata */
    meta->x = 8;
    meta->y = 8;
    meta->width = 120;
    meta->height = 80;
    [...]#include <gst/video/gstvideometa.h>

    [...]
    GstVideoCropMeta *meta;

    /* buffer points to a video frame, get the cropping metadata */
    meta = gst_buffer_get_video_crop_meta (buffer);

    if (meta) {
    /* render frame with cropping */
    _render_frame_cropped (buffer, meta->x, meta->y, meta->width, meta->height);
    } else {
    /* render frame */
    _render_frame (buffer);
    }
    [...]

    如何实现自定义的 GstMeta :Memory allocation

    GstBufferPool:

    由内存池分配的 GstBuffer 具备完全相同的 meta data,唯一不一样的就是指向的内存区域。

    GStreamer如何优化内存管理策略?

    GstBufferPool 以 GstBuffer 为管理单位,当且仅当 GstBufferPool 为 inactive 状态时,可以配置 GstBuffer 的meta data;当且仅当GstBufferPool 为 active 状态时,可以分配和销毁GstBuffer。

    GstStructure *config;

    [...]

    /* get config structure */
    config = gst_buffer_pool_get_config (pool);

    /* set caps, size, minimum and maximum buffers in the pool */
    gst_buffer_pool_config_set_params (config, caps, size, min, max);

    /* configure allocator and parameters */
    gst_buffer_pool_config_set_allocator (config, allocator, ¶ms);

    /* store the updated configuration again */
    gst_buffer_pool_set_config (pool, config);

    [...]

    The following options can be configured on a​​GstBufferPool​​:

    • The caps of the buffers to allocate.
    • The size of the buffers. This is the suggested size of the buffers in the pool. The pool might decide to allocate larger buffers to add padding.
    • The minimum and maximum amount of buffers in the pool. When minimum is set to​​\> 0​​, the bufferpool will pre-allocate this amount of buffers. When maximum is not 0, the bufferpool will allocate up to maximum amount of buffers.
    • The allocator and parameters to use. Some bufferpools might ignore the allocator and use its internal one.
    • Other arbitrary bufferpool options identified with a string. a bufferpool lists the supported options with​​gst_buffer_pool_get_options()​​and you can ask if an option is supported with​​gst_buffer_pool_has_option()​​. The option can be enabled by adding it to the configuration structure with​​gst_buffer_pool_config_add_option ()​​. These options are used to enable things like letting the pool set metadata on the buffers or to add extra configuration options for padding, for example.

    gst_buffer_pool_set_active(pool, TRUE)用来激活内存池,之后用gst_buffer_pool_acquire_buffer ()来获取内存池对象。

    [...]

    GstFlowReturn ret;
    GstBuffer *buffer;

    ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL);
    if (G_UNLIKELY (ret != GST_FLOW_OK))
    goto pool_failed;

    [...]

    GST_QUERY_ALLOCATION:

    本文共计1647个文字,预计阅读时间需要7分钟。

    GStreamer如何优化内存管理策略?

    GstMemory:管理小块实际虚拟内存GstBuffer:对象,element、plugin、application间最小数据单元,内部包含GstMemory、时间信息及其他信息GstMeta:附加在GstBuffer上


    • GstMemory:管理一小块实际的虚拟内存
    • GstBuffer:一个对象,是element、plugin、application互相信息交互的最小数据单位,内部包含GstMemory、时间信息和一些其他信息。
    • GstMeta:附加在GstBuffer上,用来提供一些描述内存的额外信息。
    • GstBufferPool:buffer池,但是只能分配尺寸固定的buffer。

    GstMemory:

    /**
    * GstMemory:
    * @mini_object: parent structure
    * @allocator: pointer to the #GstAllocator
    * @parent: parent memory block
    * @maxsize: the maximum size allocated
    * @align: the alignment of the memory
    * @offset: the offset where valid data starts
    * @size: the size of valid data
    *
    * Base structure for memory implementations. Custom memory will put this structure
    * as the first member of their structure.
    */
    struct _GstMemory {
    GstMiniObject mini_object;

    GstAllocator *allocator;

    GstMemory *parent;
    gsize maxsize;
    gsize align;
    gsize offset;
    gsize size;
    };

    GstMemory由GstAllocator创建。

    GstAllocator:

    /**
    * GstAllocator:
    * @mem_map: the implementation of the GstMemoryMapFunction
    * @mem_unmap: the implementation of the GstMemoryUnmapFunction
    * @mem_copy: the implementation of the GstMemoryCopyFunction
    * @mem_share: the implementation of the GstMemoryShareFunction
    * @mem_is_span: the implementation of the GstMemoryIsSpanFunction
    * @mem_map_full: the implementation of the GstMemoryMapFullFunction.
    * Will be used instead of @mem_map if present. (Since: 1.6)
    * @mem_unmap_full: the implementation of the GstMemoryUnmapFullFunction.
    * Will be used instead of @mem_unmap if present. (Since: 1.6)
    *
    * The #GstAllocator is used to create new memory.
    */
    struct _GstAllocator
    {
    GstObject object;

    const gchar *mem_type;

    /*< public >*/
    GstMemoryMapFunction mem_map;
    GstMemoryUnmapFunction mem_unmap;

    GstMemoryCopyFunction mem_copy;
    GstMemoryShareFunction mem_share;
    GstMemoryIsSpanFunction mem_is_span;

    GstMemoryMapFullFunction mem_map_full;
    GstMemoryUnmapFullFunction mem_unmap_full;

    /*< private >*/
    gpointer _gst_reserved[GST_PADDING - 2];

    GstAllocatorPrivate *priv;
    };

    内存分配器,是一个接口层,如果自行管理内存分配,可以自己实现这个接口。

    内存分配和使用:

    使用 gst_allocator_alloc 分配内存,此函数返回的是一个 GstMemory 指针,GstMemory内的数据必须通过 gst_memory_map 保护才可以访问,然后通过gst_memory_unmap 释放保护后别人才可以访问,类似于加锁解锁。

    [...]

    GstMemory *mem;
    GstMapInfo info;
    gint i;

    /* allocate 100 bytes */
    mem = gst_allocator_alloc (NULL, 100, NULL);

    /* get access to the memory in write mode */
    gst_memory_map (mem, &info, GST_MAP_WRITE);

    /* fill with pattern */
    for (i = 0; i < info.size; i++)
    info.data[i] = i;

    /* release memory */
    gst_memory_unmap (mem, &info);

    [...]

    GstBuffer:

    • GstBuffer内部包含了n个GstMemory,同时也包含了一些meta data:
    • dts 、pts:用来进行同步。
    • duration:buffer内数据总时长,不是整个流的总时长。
    • offset :buffer存视频时,表示当前buffer内第一帧数据在整个流中是第多少个帧;buffer存音频时,???
    • offset_end:buffer存视频时,表示当前buffer内最后一帧数据在整个流中是第多少个帧;buffer存音频时,???
    /**
    * GstBuffer:
    * @mini_object: the parent structure
    * @pool: pointer to the pool owner of the buffer
    * @pts: presentation timestamp of the buffer, can be #GST_CLOCK_TIME_NONE when the
    * pts is not known or relevant. The pts contains the timestamp when the
    * media should be presented to the user.
    * @dts: decoding timestamp of the buffer, can be #GST_CLOCK_TIME_NONE when the
    * dts is not known or relevant. The dts contains the timestamp when the
    * media should be processed.
    * @duration: duration in time of the buffer data, can be #GST_CLOCK_TIME_NONE
    * when the duration is not known or relevant.
    * @offset: a media specific offset for the buffer data.
    * For video frames, this is the frame number of this buffer.
    * For audio samples, this is the offset of the first sample in this buffer.
    * For file data or compressed data this is the byte offset of the first
    * byte in this buffer.
    * @offset_end: the last offset contained in this buffer. It has the same
    * format as @offset.
    *
    * The structure of a #GstBuffer. Use the associated macros to access the public
    * variables.
    */
    struct _GstBuffer {
    GstMiniObject mini_object;

    /*< public >*/ /* with COW */
    GstBufferPool *pool;

    /* timestamp */
    GstClockTime pts;
    GstClockTime dts;
    GstClockTime duration;

    /* media specific offset */
    guint64 offset;
    guint64 offset_end;
    };

    默认情况下GstBuffer是不可写的,需要先通过gst_buffer_make_writable函数处理,然后才可以修改里面的内容,比如dts、pts、duration、offset等等。

    三种创建GstBuffer的方法:

  • gst_buffer_new 创建GstBuffer 对象,但是创建的对象不包含 GstMemory,需要手动创建GstMemory再进行绑定;
  • gst_buffer_new_allocate 同时创建GstBuffer 和 指定数量的GstMemory,然后还会自动完成绑定动作;
  • gst_buffer_new_wrapped_full 为现有GstMemory创建一个GstBuffer。
  • [...]
    GstBuffer *buffer;
    GstMemory *mem;
    GstMapInfo info;

    /* make empty buffer */
    buffer = gst_buffer_new ();

    /* make memory holding 100 bytes */
    mem = gst_allocator_alloc (NULL, 100, NULL);

    /* add the buffer */
    gst_buffer_append_memory (buffer, mem);

    [...]

    /* get WRITE access to the memory and fill with 0xff */
    gst_buffer_map (buffer, &info, GST_MAP_WRITE);
    memset (info.data, 0xff, info.size);
    gst_buffer_unmap (buffer, &info);

    [...]

    /* free the buffer */
    gst_buffer_unref (buffer);

    [...]

    GstMeta:

    /**
    * GstMeta:
    * @flags: extra flags for the metadata
    * @info: pointer to the #GstMetaInfo
    *
    * Base structure for metadata. Custom metadata will put this structure
    * as the first member of their structure.
    */
    struct _GstMeta {
    GstMetaFlags flags;
    const GstMetaInfo *info;
    };

    GstMeta可以随意地附加到一个GstBuffer中。

    #include <gst/video/gstvideometa.h>

    [...]
    GstVideoCropMeta *meta; //GstMeta的一个子类

    /* buffer points to a video frame, add some cropping metadata */
    meta = gst_buffer_add_video_crop_meta (buffer);

    /* configure the cropping metadata */
    meta->x = 8;
    meta->y = 8;
    meta->width = 120;
    meta->height = 80;
    [...]#include <gst/video/gstvideometa.h>

    [...]
    GstVideoCropMeta *meta;

    /* buffer points to a video frame, get the cropping metadata */
    meta = gst_buffer_get_video_crop_meta (buffer);

    if (meta) {
    /* render frame with cropping */
    _render_frame_cropped (buffer, meta->x, meta->y, meta->width, meta->height);
    } else {
    /* render frame */
    _render_frame (buffer);
    }
    [...]

    如何实现自定义的 GstMeta :Memory allocation

    GstBufferPool:

    由内存池分配的 GstBuffer 具备完全相同的 meta data,唯一不一样的就是指向的内存区域。

    GStreamer如何优化内存管理策略?

    GstBufferPool 以 GstBuffer 为管理单位,当且仅当 GstBufferPool 为 inactive 状态时,可以配置 GstBuffer 的meta data;当且仅当GstBufferPool 为 active 状态时,可以分配和销毁GstBuffer。

    GstStructure *config;

    [...]

    /* get config structure */
    config = gst_buffer_pool_get_config (pool);

    /* set caps, size, minimum and maximum buffers in the pool */
    gst_buffer_pool_config_set_params (config, caps, size, min, max);

    /* configure allocator and parameters */
    gst_buffer_pool_config_set_allocator (config, allocator, ¶ms);

    /* store the updated configuration again */
    gst_buffer_pool_set_config (pool, config);

    [...]

    The following options can be configured on a​​GstBufferPool​​:

    • The caps of the buffers to allocate.
    • The size of the buffers. This is the suggested size of the buffers in the pool. The pool might decide to allocate larger buffers to add padding.
    • The minimum and maximum amount of buffers in the pool. When minimum is set to​​\> 0​​, the bufferpool will pre-allocate this amount of buffers. When maximum is not 0, the bufferpool will allocate up to maximum amount of buffers.
    • The allocator and parameters to use. Some bufferpools might ignore the allocator and use its internal one.
    • Other arbitrary bufferpool options identified with a string. a bufferpool lists the supported options with​​gst_buffer_pool_get_options()​​and you can ask if an option is supported with​​gst_buffer_pool_has_option()​​. The option can be enabled by adding it to the configuration structure with​​gst_buffer_pool_config_add_option ()​​. These options are used to enable things like letting the pool set metadata on the buffers or to add extra configuration options for padding, for example.

    gst_buffer_pool_set_active(pool, TRUE)用来激活内存池,之后用gst_buffer_pool_acquire_buffer ()来获取内存池对象。

    [...]

    GstFlowReturn ret;
    GstBuffer *buffer;

    ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL);
    if (G_UNLIKELY (ret != GST_FLOW_OK))
    goto pool_failed;

    [...]

    GST_QUERY_ALLOCATION: