gstreamer插件开发-What are states?

What are states?

状态描述元素实例是否初始化、是否准备好传输数据以及当前是否正在处理数据。在GStreamer中定义了四种状态:

  • GST_STATE_NULL
  • GST_STATE_READY
  • GST_STATE_PAUSED
  • GST_STATE_PLAYING
    从现在开始,它们将被简单地称为“NULL”、“READY”、“PAUSED”和“PLAYING”。

GST_STATE_NULL 是元素的默认状态。在这种状态下,它没有分配任何运行时资源,没有加载任何运行时库,显然它不能处理数据。

GST_STATE_READY 是元素可以进入的下一个状态。在READY状态下,元素分配了所有默认资源(运行时库、运行时内存)。然而,它还没有分配或定义任何特定于流的东西。当从NULL到READY状态(GST_STATE_CHANGE_NULL_TO_READY)时,元素应该分配任何非流特定的资源,并且应该加载运行时可加载的库(如果有的话)。当进行相反的操作时(从READY到NULL, GST_STATE_CHANGE_READY_TO_NULL),元素应该卸载这些库并释放所有已分配的资源。这种资源的例子是硬件设备。请注意,文件通常是流,因此这些文件应被视为特定于流的资源;因此,不应该在这种状态下分配它们。

GST_STATE_PAUSED 是元素准备接受和处理数据的状态。对于大多数元素,这种状态与PLAYING相同。此规则的唯一例外是接收元素。Sink元素只接受一个数据缓冲区,然后阻塞。在这一点上,管道是“预卷”,并准备立即呈现数据。

GST_STATE_PLAYING 是元素可以处于的最高状态。对于大多数元素来说,这种状态与暂停状态完全相同,它们接受并处理带有数据的事件和缓冲区。只有sink元素需要区分暂停状态和播放状态。在播放状态下,接收器元素实际渲染传入数据,例如输出音频到声卡或渲染视频图像到图像接收器。

Managing filter state

如果可能的话,您的元素应该从一个新的基类(预制基类)派生。对于不同类型的源、汇和过滤器/转换元素,有现成的通用基类。除此之外,音频和视频元素以及其他元素还存在专门的基类。

如果使用基类,则很少需要自己处理状态更改。您所要做的就是重写基类的start()和stop()虚函数(可能根据基类的不同而被不同地调用),基类将为您处理所有事情。

但是,如果您不是从现成的基类派生,而是从GstElement或其他不是构建在基类之上的类派生,那么您很可能必须实现自己的状态更改函数,以便收到状态更改的通知。如果你的插件是一个demuxer或demuxer,这是绝对必要的,因为还没有针对muxers或demuxers的基类。

可以通过虚函数指针通知元素状态更改。在这个函数中,元素可以初始化元素所需的任何类型的特定数据,并且它可以选择从一种状态切换到另一种状态。

对于未处理的状态更改不要g_assert;这是由GstElement基类处理的。

static GstStateChangeReturn
gst_my_filter_change_state (GstElement *element, GstStateChange transition);

static void
gst_my_filter_class_init (GstMyFilterClass *klass)
{
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);

  element_class->change_state = gst_my_filter_change_state;
}



static GstStateChangeReturn
gst_my_filter_change_state (GstElement *element, GstStateChange transition)
{
  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
  GstMyFilter *filter = GST_MY_FILTER (element);

  switch (transition) {
	case GST_STATE_CHANGE_NULL_TO_READY:
	  if (!gst_my_filter_allocate_memory (filter))
		return GST_STATE_CHANGE_FAILURE;
	  break;
	default:
	  break;
  }

  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
  if (ret == GST_STATE_CHANGE_FAILURE)
	return ret;

  switch (transition) {
	case GST_STATE_CHANGE_READY_TO_NULL:
	  gst_my_filter_free_memory (filter);
	  break;
	default:
	  break;
  }

  return ret;
}

请注意,向上(NULL=>READY, READY=>PAUSED, PAUSED=>PLAYING)和向下(PLAYING=>PAUSED, PAUSED=>READY, READY=>NULL)状态变化是在两个单独的块中处理的,向下的状态变化只有在我们链接到父类的状态变化函数之后才能处理。为了安全地处理多线程的并发访问,这是必要的。

这样做的原因是,在向下状态变化的情况下,你不想破坏分配的资源,而你的插件的链函数(例如)仍然在另一个线程中访问这些资源。你的链式函数是否在运行取决于插件的垫的状态,而这些垫的状态与元素的状态密切相关。Pad状态在GstElement类的状态更改函数中处理,包括适当的锁定,这就是为什么在销毁分配的资源之前必须链接起来的原因。

你可能感兴趣的:(GStreamer,gstreamer,音视频)