简化流水线
目标:使用GStreamer构建的流水线不需要完全关闭。数据可以在任何时间以各种方式注入到流水线中,或者从流水线中提取出来。
appsrc
可以以多种模式工作:在拉取模式(pull mode
)下,它在每次需要数据时,从应用程序请求数据。在推送模式(push mode
)下,应用程序以自己的速度推送数据。此外,在推送模式下,当已提供足够的数据时,应用程序可以选择在推送函数中被阻塞,或者可以监听enough-data
和need-data
来控制数据的流动。此示例实现了后一种方法。关于其他方法的信息可以在appsrc
的文档中找到。
缓冲区(Buffers)
定义:数据通过GStreamer流水线的块传输被称为缓冲区。
说明:Source pads
产生缓冲区,这些缓冲区由Sink pads
消费;GStreamer获取这些缓冲区并将它们从一个元素传递到另一个元素。
缓冲区只是表示一单位数据,不要假设所有缓冲区的大小相同,或者代表相同的时间量。也不要假设如果一个缓冲区进入一个元素,将会有一个缓冲区出来。元素可以自由处理接收到的缓冲区。GstBuffers
也可以包含多个实际内存缓冲区。通过使用GstMemory
对象抽象出实际的内存缓冲区,并且一个GstBuffer
可以包含多个GstMemory
对象。
每个缓冲区都附带有时间戳和持续时间,用于描述何时对缓冲区的内容进行解码、渲染或显示。时间戳是一个非常复杂和微妙的问题,但这种简化的视角应该足够了解。
例如:filesrc
(读取文件的GStreamer元素)产生的缓冲区具有“ANY” caps
,并且没有时间戳信息。在解复用(demuxing
)之后(见基础教程3:动态流水线),缓冲区可以有一些特定的caps
,例如“video/x-h264
”。在解码之后,每个缓冲区将包含一个单独的带有原始caps
的视频帧(例如,“video/x-raw-yuv
”),并且具有非常精确的时间戳,指示该帧应该何时显示。
注意事项
本章的部分函数调用了-lgstaudio-1.0
动态链接库,请写入CMakelist.txt
里。
函数与知识点
-
appsrc
介绍:将应用程序数据注入到GStreamer流水线中的元素是appsrc
-
appsink
介绍:用于将GStreamer数据提取回应用程序的对应元素是appsink
-
GstCaps *gst_caps_from_string (const gchar * string)
功能:将字符串表示的caps
转换为GstCaps
。 -
new-sample
介绍:在接收到缓冲区时触发。需要通过emit-signals
属性启用信号发射,因为默认情况下它是禁用的。 -
emit-signals
介绍:发出new-preroll
和new-sample
信号。类型:gboolean
。默认值:false
。 -
guint g_idle_add (GSourceFunc function, gpointer data)
功能:将一个函数添加到默认主循环中,当没有更高优先级的事件等待时,该函数将被调用。该函数被赋予默认的空闲优先级,即G_PRIORITY_DEFAULT_IDLE
。如果函数返回FALSE
,则会自动将其从事件源列表中移除,并且不会再次调用。 -
gboolean g_source_remove (guint tag)
功能:从默认主上下文中删除具有给定ID
的GSource
。对于添加到非默认主上下文的源,必须使用g_source_destroy()
。说明:
GSource
的ID
由g_source_get_id()
给出,或者将由以下函数返回:g_source_attach()、g_idle_add()、g_idle_add_full()、g_timeout_add()、g_timeout_add_full()、g_child_watch_add()、g_child_watch_add_full()、g_io_add_watch()、g_io_add_watch_full()
。 -
gst_buffer_new_and_alloc()
功能:创建一个给定大小的新缓冲区。 -
GST_BUFFER_TIMESTAMP
功能:获取缓冲区的时间戳,以纳秒(ns
)做单位 -
GST_BUFFER_DURATION
功能:获取缓冲区中数据的持续时间,以纳秒为单位(作为GstClockTime
)。 -
guint64 gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom)
功能:按有理数num / denom
缩放val
,避免溢出和下溢,并且不会丢失精度。说明:如果
val
和num
都大于G_MAXUINT32
,则此函数可能非常慢。
参数:val
- 要缩放的数字;num
- 缩放比例的分子;denom
- 缩放比例的分母 -
gboolean gst_buffer_map (GstBuffer * buffer, GstMapInfo * info, GstMapFlags flags)
功能:使用缓冲区中所有合并内存块的GstMapInfo
填充info
。cleanup:在使用后,
info
中的内存应使用gst_buffer_unmap
取消映射。 -
GstFlowReturn gst_app_src_push_buffer (GstAppSrc * appsrc, GstBuffer * buffer)
功能:将一个缓冲区添加到appsrc
元素将推送到其source pad
的缓冲区队列中。此函数接管缓冲区的所有权。说明:当
block
属性为TRUE
时,此函数可以阻塞,直到队列中有可用的空闲空间。 -
push-buffer
功能:appsrc
的信号之一。将一个缓冲区添加到appsrc元素将推送到其源pad的缓冲区队列中。说明:此函数不会接管缓冲区的所有权,但它会引用该缓冲区,因此在调用此函数后可以随时解引用该缓冲区。
例如:
g_signal_emit_by_name (data->app_source, "push-buffer", buffer, &ret);
cleanup:
gst_buffer_unref()
-
pull-sample
功能:sink
的信号之一。这个函数会阻塞直到样本或EOS可用,或者appsink元素被设置为READY/NULL状态。说明:只有当
appsink
处于PLAYING
状态时,此函数才会返回样本。所有已渲染的样本都将放入一个队列中,以便应用程序可以以自己的速度提取样本。注意:
- 当应用程序无法快速提取样本时,排队的样本可能会消耗大量内存,尤其是在处理原始视频帧时。可以使用“
drop
”和“max-buffers
”属性来控制队列的行为。 - 如果在任何缓冲区之前接收到
EOS
事件,则此函数返回NULL
。使用gst_app_sink_is_eos()
来检查EOS
条件。
例如:
g_signal_emit_by_name (appsink, "pull-sample", &ret);
- 当应用程序无法快速提取样本时,排队的样本可能会消耗大量内存,尤其是在处理原始视频帧时。可以使用“