이 장에서는 새 플러그인을 위한 최소한의 코드를 구성하는 방법을 알아봅니다. 처음부터 시작하여 GStreamer 템플릿 소스를 가져오는 방법을 알아봅니다. 그런 다음 몇 가지 기본 도구를 사용하여 템플릿 플러그인을 복사하고 수정하여 새 플러그인을 만드는 방법을 알아봅니다. 여기의 예를 따르면 이 장을 마칠 때까지 GStreamer 애플리케이션에서 컴파일하고 사용할 수 있는 기능적 오디오 필터 플러그인을 갖게 됩니다.
Getting the GStreamer Plugin Templates
현재 GStreamer용 새 플러그인을 개발하는 방법은 두 가지가 있습니다. 직접 플러그인 전체를 작성하거나 기존 플러그인 템플릿을 복사하여 필요한 플러그인 코드를 작성할 수 있습니다. 두 번째 방법은 두 가지 중 훨씬 간단하므로 첫 번째 방법은 여기서 설명하지 않겠습니다. (음, 즉 "독자에게 연습으로 남겨둡니다.")
첫 번째 단계는 gst-template git 모듈의 사본을 체크아웃하여 중요한 도구와 기본 GStreamer 플러그인의 소스 코드 템플릿을 얻는 것입니다. gst-template 모듈을 체크아웃하려면 인터넷에 연결되어 있는지 확인하고 명령 콘솔에서 다음 명령을 입력하세요.
shell $ git clone https://gitlab.freedesktop.org/gstreamer/gst-template.git
Initialized empty Git repository in /some/path/gst-template/.git/
remote: Counting objects: 373, done.
remote: Compressing objects: 100% (114/114), done.
remote: Total 373 (delta 240), reused 373 (delta 240)
Receiving objects: 100% (373/373), 75.16 KiB | 78 KiB/s, done.
Resolving deltas: 100% (240/240), done.
이 명령은 일련의 파일과 디렉토리를 gst-template으로 체크아웃합니다. 사용할 템플릿은 gst-template/gst-plugin/ 디렉토리에 있습니다. 플러그인의 소스 트리 구조에 대한 일반적인 아이디어를 얻으려면 해당 디렉토리의 파일을 살펴봐야 합니다.
어떤 이유로 git 저장소에 액세스할 수 없는 경우 gitlab 웹 인터페이스를 통해 최신 개정판의 스냅샷을 다운로드할 수도 있습니다.
Using the Project Stamp
새 element를 만들 때 가장 먼저 해야 할 일은 element에 대한 몇 가지 기본 세부 정보를 지정하는 것입니다. 이름, 작성자, 버전 번호 등입니다. 또한 element를 나타내고 element에 필요한 데이터를 저장할 객체를 정의해야 합니다. 이러한 세부 정보를 통틀어 boilerplate라고 합니다.
boilerplate를 정의하는 표준적인 방법은 간단히 코드를 작성하고 구조를 채우는 것입니다. 이전 섹션에서 언급했듯이 가장 쉬운 방법은 템플릿을 복사하여 필요에 따라 기능을 추가하는 것입니다. 이를 돕기 위해 ./gst-plugin/tools/ 디렉터리에 도구가 있습니다. 이 도구인 make_element는 boilerplate 코드를 생성하는 커맨드라인 유틸리티입니다.
make_element를 사용하려면 먼저 터미널 창을 엽니다. gst-template/gst-plugin/src 디렉터리로 변경한 다음 make_element 명령을 실행합니다. make_element에 대한 인수는 다음과 같습니다.
- 플러그인의 이름, 그리고
- 도구가 사용할 소스 파일. 기본적으로 gstplugin이 사용됩니다.
예를 들어, 다음 명령은 플러그인 템플릿을 기반으로 MyFilter 플러그인을 만들고 출력 파일을 gst-template/gst-plugin/src 디렉토리에 넣습니다.
shell $ cd gst-template/gst-plugin/src
shell $ ../tools/make_element MyFilter
Note
플러그인 이름에는 대문자가 중요합니다. 일부 운영 체제에서는 디렉토리 및 파일 이름을 일반적으로 지정할 때도 대문자가 중요하다는 점을 명심하세요.
마지막 명령은 gstmyfilter.c와 gstmyfilter.h라는 두 개의 파일을 생성합니다.
Note
계속하기 전에 gst-plugin 디렉토리의 사본을 만드는 것이 좋습니다.
이제 부모 디렉토리에서 meson setup build를 실행하여 빌드 환경을 부트스트랩해야 합니다. 그런 다음 잘 알려진 ninja -C build 명령을 사용하여 프로젝트를 빌드하고 설치할 수 있습니다.
Note
기본적으로 meson은 /usr/local을 기본 위치로 선택합니다. 패키지에서 설치된 gstreamer에 새 플러그인이 표시되도록 하려면 /usr/local/lib/gstreamer-1.0을 GST_PLUGIN_PATH에 추가해야 합니다.
Note
FIXME: 이 섹션은 약간 오래되었습니다. gst-template은 최소한의 플러그인 빌드 시스템 골격의 예로 여전히 유용합니다. 그러나 element를 만드는 경우 요즘은 gst-plugins-bad의 도구 gst-element-maker가 권장됩니다.
Examining the Basic Code
먼저 헤더 파일에 넣을 만한 코드를 살펴보겠습니다 (하지만 코드의 인터페이스는 플러그인 시스템에 의해 완전히 정의되고 헤더 파일을 읽는 데 의존하지 않으므로 이는 중요하지 않습니다).
#include <gst/gst.h>
/* Definition of structure storing data for this element. */
typedef struct _GstMyFilter {
GstElement element;
GstPad *sinkpad, *srcpad;
gboolean silent;
} GstMyFilter;
/* Standard definition defining a class for this element. */
typedef struct _GstMyFilterClass {
GstElementClass parent_class;
} GstMyFilterClass;
/* Standard macros for defining types for this element. */
#define GST_TYPE_MY_FILTER (gst_my_filter_get_type())
#define GST_MY_FILTER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MY_FILTER,GstMyFilter))
#define GST_MY_FILTER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MY_FILTER,GstMyFilterClass))
#define GST_IS_MY_FILTER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MY_FILTER))
#define GST_IS_MY_FILTER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MY_FILTER))
/* Standard function returning type information. */
GType gst_my_filter_get_type (void);
GST_ELEMENT_REGISTER_DECLARE(my_filter)
이 헤더 파일을 사용하면 다음 매크로를 사용하여 소스 파일에서 Element 기본을 설정하여 모든 함수가 적절하게 호출되도록 할 수 있습니다.
#include "filter.h"
G_DEFINE_TYPE (GstMyFilter, gst_my_filter, GST_TYPE_ELEMENT);
GST_ELEMENT_REGISTER_DEFINE(my_filter, "my-filter", GST_RANK_NONE, GST_TYPE_MY_FILTER);
GST_ELEMENT_REGISTER_DEFINE 매크로를 GST_ELEMENT_REGISTER_DECLARE와 함께 사용하면 플러그인 내부에서 또는 다른 플러그인/애플리케이션에서 GST_ELEMENT_REGISTER(my_filter)를 호출하여 element를 등록할 수 있습니다.
Element metadata
Element 메타데이터는 추가 element 정보를 제공합니다. 다음 매개변수를 사용하는 gst_element_class_set_metadata 또는 gst_element_class_set_static_metadata로 구성됩니다.
- Element의 이름. 길게 영어로 만들짐.
- Element의 유형, 자세한 내용과 예는 GStreamer 코어 소스 트리의 docs/additional/design/draft-klass.txt 문서를 참조하세요.
- Element의 목적에 대한 간략한 설명.
- Element 작성자 이름, 선택적으로 꺾쇠 괄호로 묶인 연락처 이메일 주소가 뒤에 붙습니다.
예를 들어:
gst_element_class_set_static_metadata (klass,
"An example plugin",
"Example/FirstExample",
"Shows the basic structure of a plugin",
"your name <your.name@your.isp>");
Element 세부 정보는 GObject 시스템의 일부인 _class_init() 함수 중에 플러그인에 등록됩니다. _class_init() 함수는 GLib에 유형을 등록하는 함수에서 이 GObject에 대해 설정해야 합니다.
static void
gst_my_filter_class_init (GstMyFilterClass * klass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
[..]
gst_element_class_set_static_metadata (element_class,
"An example plugin",
"Example/FirstExample",
"Shows the basic structure of a plugin",
"your name <your.name@your.isp>");
}
GstStaticPadTemplate
GstStaticPadTemplate은 element가 만들고 사용할 (또는 만들 수 있는) pad에 대한 설명입니다. 여기에는 다음이 포함됩니다.
- Pad의 약어입니다.
- Pad 방향입니다.
- 존재 속성입니다. Pad가 항상 존재하는지 ("always" pad), 어떤 경우에만 존재하는지 ("sometimes" pad) 또는 애플리케이션에서 해당 pad를 요청한 경우에만 존재하는지 ("request" pad)를 나타냅니다.
- 이 element에서 지원하는 유형 (capabilities).
예를 들어:
static GstStaticPadTemplate sink_factory =
GST_STATIC_PAD_TEMPLATE (
"sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("ANY")
);
이러한 pad 템플릿은 gst_element_class_add_pad_template()를 사용하여 _class_init() 함수 중에 등록됩니다. 이 함수의 경우 gst_static_pad_template_get()을 사용하여 static pad 템플릿에서 만들 수 있는 GstPadTemplate에 대한 핸들이 필요합니다. 자세한 내용은 아래를 참조하세요.
Pad는 gst_pad_new_from_static_template()를 사용하여 element의 _init() 함수에서 이러한 static 템플릿에서 생성됩니다. gst_pad_new_from_static_template()을 사용하여 이 템플릿에서 새 pad를 만들려면 pad 템플릿을 전역 변수로 선언해야 합니다. 이 주제에 대한 자세한 내용은 Specifying the pads에서 확인하세요.
static GstStaticPadTemplate sink_factory = [..],
src_factory = [..];
static void
gst_my_filter_class_init (GstMyFilterClass * klass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
[..]
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&src_factory));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_factory));
}
템플릿의 마지막 인수는 지원되는 유형의 유형 또는 목록입니다. 이 예에서 'ANY'를 사용하는데, 이는 이 element가 모든 입력을 허용한다는 것을 의미합니다. 실제 상황에서는 미디어 유형과 선택적으로 속성 집합을 설정하여 지원되는 입력만 들어오도록 합니다. 이 표현은 미디어 유형으로 시작하는 문자열이어야 하며, 그 다음에 지원되는 값이 있는 쉼표로 구분된 속성 집합이어야 합니다. 모든 samplerate에서 raw integet 16비트 오디오, 모노 또는 스테레오를 지원하는 오디오 필터의 경우 올바른 템플릿은 다음과 같습니다.
static GstStaticPadTemplate sink_factory =
GST_STATIC_PAD_TEMPLATE (
"sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (
"audio/x-raw, "
"format = (string) " GST_AUDIO_NE (S16) ", "
"channels = (int) { 1, 2 }, "
"rate = (int) [ 8000, 96000 ]"
)
);
중괄호로 둘러싼 값 ("{" 및 "}")은 목록이고, 대괄호로 둘러싼 값 ("[" 및 "]")은 범위입니다. 여러 유형의 집합도 지원되며 세미콜론 (";")으로 구분해야 합니다. 나중에 pad에 대한 장에서 유형을 사용하여 스트림의 정확한 형식을 아는 방법을 살펴보겠습니다 (Specifying the pads).
Constructor Functions
각 element에는 element 생성에 사용되는 두 가지 함수가 있습니다. _class_init() 함수는 클래스를 단 한 번만 초기화하는 데 사용됩니다 (클래스가 가진 신호, 인수 및 가상 함수를 지정하고 전역 상태를 설정). _init() 함수는 이 유형의 특정 인스턴스를 초기화하는 데 사용됩니다.
The plugin_init function
플러그인의 모든 부분을 정의하는 코드를 작성했으면 plugin_init() 함수를 작성해야 합니다. 이것은 플러그인이 로드되는 즉시 호출되는 특수 함수이며, 로드된 종속성이 올바르게 초기화되었는지 여부에 따라 TRUE 또는 FALSE를 반환해야 합니다. 또한 이 함수에서, 플러그인에서 지원되는 모든 element 유형은 등록되어야 합니다.
static gboolean
plugin_init (GstPlugin *plugin)
{
return GST_ELEMENT_REGISTER (my_filter, plugin);
}
GST_PLUGIN_DEFINE (
GST_VERSION_MAJOR,
GST_VERSION_MINOR,
my_filter,
"My filter plugin",
plugin_init,
VERSION,
"LGPL",
"GStreamer",
"http://gstreamer.net/"
)
plugin_init() 함수에서 반환된 정보는 중앙 레지스트리에 캐시됩니다. 이러한 이유로 함수에서 항상 동일한 정보를 반환하는 것이 중요합니다. 예를 들어, 런타임 조건에 따라 element factory를 사용 가능하게 만들어서는 안 됩니다. Element가 특정 조건에서만 작동할 수 있는 경우 (예: 사운드카드가 다른 프로세스에서 사용되지 않는 경우) 플러그인이 플러그인의 존재를 거부하려고 시도하는 것이 아니라, element가 사용 불가능할 경우 READY 상태로 전환할 수 없음을 통해 반영되어야 합니다.
원문: Constructing the Boilerplate (gstreamer.freedesktop.org)
Constructing the Boilerplate
Constructing the Boilerplate In this chapter you will learn how to construct the bare minimum code for a new plugin. Starting from ground zero, you will see how to get the GStreamer template source. Then you will learn how to use a few basic tools to copy
gstreamer.freedesktop.org
'IT와 개발 > GStreamer Study' 카테고리의 다른 글
The chain function (0) | 2024.09.06 |
---|---|
Specifying the pads (1) | 2024.08.30 |
Plugin Writer's Guide: Foundations (0) | 2024.08.16 |
Things to check when writing an application (0) | 2024.08.09 |
Programs (1) | 2024.08.02 |