GStreamer pwg ch 7 ~ 9
7. The query function
query function으로
element는 queries를 받을 수 있음
query types
n position
n duration
n supported formats
n scheduling modes
travel
n upstream과 downstream 둘 다 이동 가능
n sink pads와 source pads에서 다 받을 수 있음
static gboolean gst_my_filter_src_query (GstPad *pad, GstObject *parent, GstQuery *query); [..] static void gst_my_filter_init (GstMyFilter * filter) { [..] /* configure event function on the pad before adding * the pad to the element */ gst_pad_set_query_function (filter->srcpad, gst_my_filter_src_query); [..] } static gboolean gst_my_filter_src_query (GstPad *pad, GstObject *parent, GstQuery *query) { gboolean ret; GstMyFilter *filter = GST_MY_FILTER (parent); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: /* we should report the current position */ [...] break; case GST_QUERY_DURATION: /* we should report the duration here */ [...] break; case GST_QUERY_CAPS: /* we should report the supported caps here */ [...] break; default: /* just call the default handler */ ret = gst_pad_query_default (pad, parent, query); break; } return ret; } |
모르는 query에 대해서는 default query handler인 gst_pad_query_default()를 호출하는 것이 좋음
이는 query를 전달하던가 혹은 unref 함
8. What are states?
state는 상태를 설명함
상태 종류 (4가지)
n GST_STATE_NULL
s 자원이 할당되지 않은 상태
n GST_STATE_READY
s 기본 자원들 (lib들 포함)이 할당된 상태
s stream-specific한 것은 할당되지 않은 상태
s GST_STATE_CHANGE_NULL_TO_READY
- NULL에서 READY로 전환하는 상태
- non-stream-specific 자원을 할당해야 함 (lib loading 포함)
s GST_STATE_CHANGE_READY_TO_NULL
- 할당 한 것들을 unload
n ex. hardware device 등
n file은 stream 자원임 (stream-specific resource)
n GST_STATE_PAUSED
s data를 받아들일 상태가 되었음
s 보통의 element에서 이는 PLAYING과 동일한 상태
- 차이는 sink에만 있음
- sink element는 하나의 버퍼만 받아들이고 block
- 이 시점이 pipeline이 'prerolled'이며
n 이는 data를 즉각 render할 준비가 된 상태임
n GST_STATE_PLAYING
s PAUSED와 거의 동일
s 차이는
- buffer의 data를 처리한다는 점
- sink element만 paused와 playing 상태를 구분함
n sink element는 data를 rendering 수행
8.1. managing filter state
Pre-made base class들을 사용할 경우 state 처리에 대해 별로 할 것은 없다.
할 것은 class의
start와 stop의 override
n base class에 의해서 호출됨
ready-made class를 derived하지 않을 경우
GstElement나 다른 class가 base class 위에 만들어지지 않은 경우
state change function을 직접 구현해야 함
n stage change의 변경을 notify 받기 위한 함수를 구현해야 함
n demuxer나 muxer인 경우 필요함
s demuxer, muxer는 base class가 없음
모든 element는 state change를 virtual function pointer를 통해서 noti 받음
이 함수 내에서 element는 필요한 초기화를 수행해야 함
다뤄지지 않은 state change는 GstElement base class가 처리함
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; } |
upwards
n NULL à READY
n READY à PAUSED
n PAUSED à PLAYING
downwards
n PLAYING à PAUSED
n PAUSED à READY
n READY à NULL
upward와 downward의 state change는 각각 다른 block에서 처리됨
n parent의 state change function을 chain up 한 이후에야 downward state change가 handle됨
s 여러thread에 의한 동시 접속에 안전을 기하기 위함
downwards state change의 경우
n plugin의 chain 함수가 여전히 다른 thread에 의해 access 될 때 할당된 resource의 해제를 원치 않을 수 있음
n chain 함수가 plugin의 pad 상태에 의존하여 동작하던 아니던, pad들이 element의 상태에 밀접하게 열결 되었던
s pad의 state는 GstElement class의 state change 함수에서 처리됨
- 적절한 locking을 포함
s 이것이 자원 해제 전에 chain up 해야 하는 1이유임
9. Adding Properties
element의 동작은
GObject property 설정에 따라 달라짐
_class_init에서 GObject property가 정의되며 아래 함수들을 구현할 수 있음
n _get_property
n _set_property
이 함수들은 application이 property 값에 변경 및 read 요청을 하면 호출 됨
n 이 함수 내에서 값을 채우던가 적절한 value 변경을 수행함
default value
GOjbect는 자동으로 default value를 설정하지 않음
_init에서 명시적으로 설정 해 줘야 함
/* properties */ enum { PROP_0, PROP_SILENT /* FILL ME */ }; static void gst_my_filter_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void gst_my_filter_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void gst_my_filter_class_init (GstMyFilterClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); /* define virtual function pointers */ object_class->set_property = gst_my_filter_set_property; object_class->get_property = gst_my_filter_get_property; /* define properties */ g_object_class_install_property (object_class, PROP_SILENT, g_param_spec_boolean ("silent", "Silent", "Whether to be very verbose or not", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static void gst_my_filter_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GstMyFilter *filter = GST_MY_FILTER (object); switch (prop_id) { case PROP_SILENT: filter->silent = g_value_get_boolean (value); g_print ("Silent argument was changed to %s\n", filter->silent ? "true" : "false"); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gst_my_filter_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GstMyFilter *filter = GST_MY_FILTER (object); switch (prop_id) { case PROP_SILENT: g_value_set_boolean (value, filter->silent); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } |
property 추가 시,
값의 range의 valid 여부 처리
descriptive string 추가
상수값 대신 enum 등의 값 사용
property가 유용하게 사용되는 example (from videotestsrc)
typedef enum { GST_VIDEOTESTSRC_SMPTE, GST_VIDEOTESTSRC_SNOW, GST_VIDEOTESTSRC_BLACK } GstVideotestsrcPattern; [..] #define GST_TYPE_VIDEOTESTSRC_PATTERN (gst_videotestsrc_pattern_get_type ()) static GType gst_videotestsrc_pattern_get_type (void) { static GType videotestsrc_pattern_type = 0; if (!videotestsrc_pattern_type) { static GEnumValue pattern_types[] = { { GST_VIDEOTESTSRC_SMPTE, "SMPTE 100% color bars", "smpte" }, { GST_VIDEOTESTSRC_SNOW, "Random (television snow)", "snow" }, { GST_VIDEOTESTSRC_BLACK, "0% Black", "black" }, { 0, NULL, NULL }, }; videotestsrc_pattern_type = g_enum_register_static ("GstVideotestsrcPattern", pattern_types); } return videotestsrc_pattern_type; } [..] static void gst_videotestsrc_class_init (GstvideotestsrcClass *klass) { [..] g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PATTERN, g_param_spec_enum ("pattern", "Pattern", "Type of test pattern to generate", GST_TYPE_VIDEOTESTSRC_PATTERN, GST_VIDEOTESTSRC_SMPTE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); [..] } |
'Multimedia > GStreamer' 카테고리의 다른 글
GStreamer pwg ch. 3 (0) | 2021.12.22 |
---|---|
GStreamer pwg ch 4~6 (0) | 2021.12.22 |
GStreamer pwg ch 11 (0) | 2021.12.22 |
GStreamer pwg: ch 12 (0) | 2021.12.22 |
GStreamer pwg: ch 13 (0) | 2021.12.22 |
댓글