State는 element 인스턴스가 초기화되었는지, 데이터를 전송할 준비가 되었는지, 현재 데이터를 처리하고 있는지 여부를 설명합니다. GStreamer에는 네 가지 state가 정의되어 있습니다.
- GST_STATE_NULL
- GST_STATE_READY
- GST_STATE_PAUSED
- GST_STATE_PLAYING
이제부터는 간단히 "NULL", "READY", "PAUSED" 및 "PLAYING"이라고 합니다.
GST_STATE_NULL은 element의 기본 state입니다. 이 state에서는 런타임 리소스를 할당하지 않았고, 런타임 라이브러리를 로드하지 않았으며, 분명히 데이터를 처리할 수 없습니다.
GST_STATE_READY는 element가 가질 수 있는 다음 state입니다. READY state에서는 element에 모든 기본 리소스 (런타임 라이브러리, 런타임 메모리)가 할당됩니다. 그러나 스트림에 특정한 것은 아직 할당하거나 정의하지 않았습니다. NULL에서 READY state (GST_STATE_CHANGE_NULL_TO_READY)로 전환할 때 element는 스트림에 특정하지 않은 리소스를 할당하고 런타임에 로드할 수 있는 라이브러리 (있는 경우)를 로드해야 합니다. 반대로 전환할 때 (READY에서 NULL로, GST_STATE_CHANGE_READY_TO_NULL) element는 이러한 라이브러리를 언로드하고 할당된 모든 리소스를 해제해야 합니다. 이러한 리소스의 예로는 하드웨어 장치가 있습니다. 파일은 일반적으로 스트림이며, 따라서 스트림별 리소스로 간주되어야 하므로 이 state에서는 할당해서는 안 됩니다.
GST_STATE_PAUSED는 element가 데이터를 수락하고 처리할 준비가 된 상태입니다. 대부분의 element의 경우 이 state는 PLAYING과 같습니다. 이 규칙의 유일한 예외는 sink element입니다. Pause 된 sink element는 데이터 버퍼 하나만 수락한 다음 차단합니다. 이 시점에서 파이프라인은 'prerolled' 되어 데이터를 즉시 렌더링할 준비가 됩니다.
GST_STATE_PLAYING은 element가 있을 수 있는 가장 높은 state입니다. 대부분의 element의 경우 이 상태는 PAUSED와 정확히 같으며 데이터가 있는 이벤트와 버퍼를 수락하고 처리합니다. Sink element만 PAUSED와 PLAYING 상태를 구별해야 합니다. PLAYING 상태에서 sink element는 실제로 들어오는 데이터를 렌더링합니다 (예: 사운드 카드에 오디오를 출력하거나 image sink에 비디오 사진을 렌더링).
Managing filter state
가능하다면, 귀하의 element는 pre-made base classes 중 하나에서 파생되어야 합니다. 이는 다양한 유형의 source, sink 및 filter/transformation element에 대한 ready-made 범용 base 클래스입니다. 이러한 클래스 외에도 오디오 및 비디오 element와 기타에 대한 특수 base 클래스가 있습니다.
Base 클래스를 사용하는 경우 상태 변경을 직접 처리해야 하는 경우는 거의 없습니다. 해야 할 일은 base 클래스의 start() 및 stop() 가상 함수 (base 클래스에 따라 다르게 호출될 수 있음)를 재정의하는 것뿐이며, base 클래스가 모든 것을 처리해 줄 것입니다.
그러나 ready-made base 클래스에서 파생하지 않고 GstElement 또는 base 클래스 위에 구축되지 않은 다른 클래스에서 파생하는 경우, state 변경에 대한 알림을 받으려면 자체 state 변경 함수를 구현해야 할 가능성이 큽니다. 플러그인이 demuxer 또는 muxer 인 경우, 아직 muxer 또는 demuxer에 대한 base 클래스가 없으므로 이는 반드시 필요합니다.
Element는 가상 함수 포인터를 통해 state 변경에 대한 알림을 받을 수 있습니다. 이 함수 내부에서 element는 element에 필요한 모든 종류의 특정 데이터를 초기화할 수 있으며, 선택적으로 한 state에서 다른 state로 이동하는 데 실패할 수 있습니다.
처리되지 않은 state 변경에 대해 g_assert를 수행하지 마십시오. 이는 GstElement base 클래스에서 처리합니다.
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) state 변경은 두 개의 별도 블록에서 처리되며 아래쪽 state 변경은 부모 클래스의 state 변경 함수에 체인을 연결한 후에만 처리됩니다. 이는 여러 스레드의 동시 액세스를 안전하게 처리하기 위해 필요합니다.
그 이유는 아래쪽 state 변경의 경우 플러그인의 체인 함수가 다른 스레드에서 해당 리소스에 액세스하는 동안 할당된 리소스를 파괴하고 싶지 않기 때문입니다. 체인 함수가 실행 중인지 여부는 플러그인 pad의 state에 따라 달라지며 해당 pad의 state는 element의 state와 밀접하게 연결되어 있습니다. Pad state는 적절한 잠금을 포함하여 GstElement 클래스의 state 변경 함수에서 처리되므로 할당된 리소스를 파괴하기 전에 체인을 연결하는 것이 필수적입니다.
원문: What are states? (gstreamer.freedesktop.org)
'IT와 개발 > GStreamer Study' 카테고리의 다른 글
Building a Test Application (7) | 2024.10.11 |
---|---|
Adding Properties (1) | 2024.10.04 |
The query function (3) | 2024.09.20 |
The event function (0) | 2024.09.13 |
The chain function (0) | 2024.09.06 |