Elements에서 본 것처럼 pad는 외부 세계에 대한 element의 인터페이스입니다. 데이터는 한 element의 source pad에서 다른 element의 sink pad로 스트리밍됩니다. Element가 처리할 수 있는 특정 타입의 미디어는 pad의 기능에 의해 노출됩니다. 이 챕터의 뒷부분에서 capability에 대해 더 자세히 설명하겠습니다(Capabilities of a pad 참조).
Pads
Pad 타입은 방향과 가용성이라는 두 가지 속성으로 정의됩니다. 이전에 언급했듯이 GStreamer는 source pad와 sink pad라는 두 가지 pad 방향을 정의합니다. 이 용어는 element 내부의 관점에서 정의됩니다. Element는 sink pad에서 데이터를 수신하고 source pad에서 데이터를 생성합니다. 개략적으로, sink pad는 element의 왼쪽에 그려지고, source pad는 element의 오른쪽에 그려집니다. 이러한 그래프에서는 데이터가 왼쪽에서 오른쪽으로 흐릅니다. [1]
Pad 사용법은 패드 가용성에 비해 매우 간단합니다. Pad는 always, sometimes, 그리고 request 시라는 세 가지 가용성 중 하나를 가질 수 있습니다. 이 세 가지 타입의 의미는 정확히 다음과 같습니다. Always pad는 항상 존재하고, sometimes pad는 apd가 특정 경우에만 존재하며 (무작위로 사라질 수 있음), 그리고 request 시 pad는 애플리케이션에서 명시적으로 요청하는 경우에만 나타납니다.
Dynamic (or sometimes) pads
일부 element에는 element가 생성될 때 일부 pad가 없을 수도 있습니다. 예를 들어 Ogg demuxer element에서 이런 일이 발생할 수 있습니다. Element는 Ogg 스트림을 읽고 Ogg 스트림에서 해당 스트림을 감지하면 포함된 각 기본 스트림 (vorbis, theora)에 대해 동적 pad를 생성합니다. 마찬가지로 스트림이 끝나면 pad를 삭제합니다. 이 원리는 demux element 등에서 매우 유용합니다.
gst-inspect-1.0 oggdemux를 실행하면 element에 'sink'라는 sink pad 하나만 있는 것으로 표시됩니다. 다른 pad는 "휴면" 상태입니다. "가용성: sometimes" 속성이 있으므로 pad 템플릿에서 이를 확인할 수 있습니다. 재생하는 Ogg 파일 유형에 따라 pad가 생성됩니다. 동적 파이프라인을 생성할 때 이것이 매우 중요하다는 것을 알게 될 것입니다. Element에 signal handler를 연결하여 element가 "sometimes" pad 템플릿 중 하나에서 새 pad를 생성했을 때 이를 알릴 수 있습니다. 다음 코드는 이를 수행하는 방법의 예입니다.
#include <gst/gst.h>
static void
cb_new_pad (GstElement *element,
GstPad *pad,
gpointer data)
{
gchar *name;
name = gst_pad_get_name (pad);
g_print ("A new pad %s was created\n", name);
g_free (name);
/* 여기서는 새로 생서된 pad에 대한 새로운 pad 링크를 설정할 것입니다 */
[..]
}
int
main (int argc,
char *argv[])
{
GstElement *pipeline, *source, *demux;
GMainLoop *loop;
/* init */
gst_init (&argc, &argv);
/* create elements */
pipeline = gst_pipeline_new ("my_pipeline");
source = gst_element_factory_make ("filesrc", "source");
g_object_set (source, "location", argv[1], NULL);
demux = gst_element_factory_make ("oggdemux", "demuxer");
/* Element들이 적절하게 생성되었는지 검사 합니다. */
/* put together a pipeline */
gst_bin_add_many (GST_BIN (pipeline), source, demux, NULL);
gst_element_link_pads (source, "src", demux, "sink");
/* listen for newly created pads */
g_signal_connect (demux, "pad-added", G_CALLBACK (cb_new_pad), NULL);
/* start the pipeline */
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (loop);
[..]
}
"pad-added" 콜백 내에서만 파이프라인에 element를 추가하는 것은 드문 일이 아닙니다. 이렇게 하려면 gst_element_set_state() 또는 gst_element_sync_state_with_parent()를 사용하여 새로 추가된 element의 상태를 파이프라인의 대상 상태로 설정하는 것을 잊지 마세요.
Request pads
Element에는 request pad가 있을 수도 있습니다. 이러한 pad는 자동으로 생성되지 않고 request 시에만 생성됩니다. 이는 multiplexers, aggregators, 그리고 tee element 들에 매우 유용합니다. Aggregator는 여러 입력 스트림의 콘텐츠를 하나의 출력 스트림으로 병합하는 요소입니다. Tee 요소는 그 반대입니다. 이는 하나의 입력 스트림을 갖고 이 스트림을 request 시 생성되는 각 출력 pad에 복사하는 요소입니다. 애플리케이션에 스트림의 또 다른 복사본이 필요할 때마다 간단히 tee element에서 새 출력 pad를 요청할 수 있습니다.
다음 코드는 "tee" element에서 새 출력 pad를 요청하는 방법을 보여줍니다.
static void
some_function (GstElement * tee)
{
GstPad *pad;
gchar *name;
pad = gst_element_request_pad_simple (tee, "src%d");
name = gst_pad_get_name (pad);
g_print ("A new pad %s was created\n", name);
g_free (name);
/* here, you would link the pad */
/* [..] */
/* and, after doing that, free our reference */
gst_object_unref (GST_OBJECT (pad));
}
gst_element_request_pad_simple() 메소드를 사용하면 pad 템플릿 이름을 기반으로 element에서 pad를 가져올 수 있습니다. 다른 pad 템플릿과 호환되는 pad를 request하는 것도 가능합니다. 이는 element를 multiplexer element에 연결하고 호환되는 pad를 request해야 하는 경우 매우 유용합니다. 다음 예제와 같이 gst_element_get_ Compatible_pad() 메서드를 사용하여 호환 가능한 pad를 request할 수 있습니다. 모든 입력에서 Ogg 멀티플렉서의 호환 가능한 pad를 request합니다.
static void
link_to_multiplexer (GstPad * tolink_pad, GstElement * mux)
{
GstPad *pad;
gchar *srcname, *sinkname;
srcname = gst_pad_get_name (tolink_pad);
pad = gst_element_get_compatible_pad (mux, tolink_pad, NULL);
gst_pad_link (tolink_pad, pad);
sinkname = gst_pad_get_name (pad);
gst_object_unref (GST_OBJECT (pad));
g_print ("A new pad %s was created and linked to %s\n", sinkname, srcname);
g_free (sinkname);
g_free (srcname);
}
Capabilities of a pad
Pad는 element가 외부 세계에 어떻게 표시되는지에 매우 중요한 역할을 하기 때문에 capabilities를 사용하여 pad를 통해 흐를 수 있거나 현재 흐르는 데이터를 설명하는 메커니즘이 구현됩니다. 여기서는 개념을 이해할 수 있을 만큼 capabilities 가 무엇인지, 어떻게 사용하는지 간략하게 설명하겠습니다. Capabilities 에 대한 심층적인 조사와 GStreamer에 정의된 모든 capabilities 목록은 Plugin Writer's Guide를 참조하세요.
Capabilities은 pad 템플릿과 pad에 연결됩니다. Pad 템플릿의 경우 이 템플릿으로 생성된 pad를 통해 스트리밍할 수 있는 미디어 타입을 설명합니다. Pad의 경우 pad가 아직 협상되지 않은 경우 가능한 caps 목록 (일반적으로 pad 템플릿 capabilities 의 복사본)이거나, 이미 Pad가 협상 되었을 경우 현재 이 pad를 통해 스트리밍되는 미디어 타입일 수 있습니다.
Dissecting capabilities
Pad의 Capabilities은 GstCaps object에 설명되어 있습니다. 내부적으로 GstCaps에는 하나의 미디어 타입을 설명하는 하나 이상의 GstStructure가 포함됩니다. 협상된 pad에는 정확히 하나의 structure를 포함하는 Capabilities 세트가 있습니다. 또한 이 structure에는 고정된 값만 포함됩니다. 협상되지 않은 pad나 pad 템플릿에는 이러한 제약 조건이 적용되지 않습니다.
예를 들어, 아래는 gst-inspect vorbisdec를 실행하여 얻을 수 있는 "vorbisdec" element의 capabilities 내용입니다. Source pad와 sink pad라는 두 개의 pad가 표시됩니다. 이 두 pad는 모두 항상 (always) 사용할 수 있으며 둘 다 capabilities이 연결되어 있습니다. Sink pad는 미디어 타입이 "audio/x-vorbis"인 vorbis로 인코딩된 오디오 데이터를 허용합니다. Source pad는 raw 오디오 미디어 타입 (이 경우 "audio/x-raw")을 사용하여 raw (디코딩된) 오디오 샘플을 다음 element로 보내는 데 사용됩니다. Source pad에는 오디오 samplerate와 채널 수에 대한 속성과 함께 지금은 걱정할 필요가 없는 몇 가지 속성도 포함됩니다.
Pad Templates:
SRC template: 'src'
Availability: Always
Capabilities:
audio/x-raw
format: F32LE
rate: [ 1, 2147483647 ]
channels: [ 1, 256 ]
SINK template: 'sink'
Availability: Always
Capabilities:
audio/x-vorbis
Properties and values
속성은 capabilities에 대한 추가 정보를 설명하는데 사용됩니다. 속성은 key (문자열)와 value로 구성됩니다. 사용할 수 있는 다양한 value 타입이 있습니다.
- Basic 타입은 Glib에 등록된 거의 모든 GType이 될 수 있습니다. 이러한 속성은 이 속성에 대한 특정하고 비동적인 값을 나타냅니다. 예는 다음과 같습니다:
- Integer value (G_TYPE_INT): 속성에 정확한 값이 있습니다.
- Boolean value (G_TYPE_BOOLEAN): 속성은 TRUE 또는 FALSE입니다.
- Float value (G_TYPE_FLOAT): 속성에는 정확한 부동 소수점 값이 있습니다.
- String value (G_TYPE_STRING): 속성에 UTF-8 문자열이 포함되어 있습니다.
- Fraction value (GST_TYPE_FRACTION): 정수 분자와 분모로 표현된 분수를 포함합니다.
- Range 타입은 가능한 value의 범위를 나타내기 위해 GStreamer에 의해 등록된 GType입니다. 허용되는 오디오 samplerate value나 지원되는 비디오 크기를 나타내는데 사용됩니다. GStreamer에 정의된 세 가지 타입은 다음과 같습니다.
- Integer range value (GST_TYPE_INT_RANGE): 이 속성은 하한 및 상한이 있는 가능한 정수 범위를 나타냅니다. 예를 들어 "vorbisdec" element의 rate 속성은 8000에서 50000 사이일 수 있습니다.
- Float range value (GST_TYPE_FLOAT_RANGE): 이 속성은 하한 및 상한을 포함하여 가능한 부동 소수점 값의 범위를 나타냅니다.
- Fraction range value (GST_TYPE_FRACTION_RANGE): 이 속성은 하한 및 상한을 포함하여 가능한 분수 값의 범위를 나타냅니다.
- List value (GST_TYPE_LIST): 속성은 제공된 basic value list에서 모든 값을 가져올 수 있습니다.
예: 44100Hz의 samplerate와 48000Hz의 samplerate가 지원된다는 것을 표현하는 caps는 정수 값 목록을 사용하며, 하나의 값은 44100이고 다른 하나의 값은 48000입니다. - 배열 값(GST_TYPE_ARRAY): 속성은 값의 배열입니다. 배열의 각 값은 그 자체로도 전체 값입니다. 배열의 모든 값은 동일한 기본 유형이어야 합니다. 즉, 배열에는 정수, 정수 목록, 정수 범위의 모든 조합이 포함될 수 있으며 부동 소수점이나 문자열도 마찬가지지만 부동 소수점과 정수가 동시에 포함될 수는 없습니다.
예: 오디오에서 두 개 이상의 채널이 있는 경우 채널 레이아웃을 명시해야 합니다 ( 단일 및 이중 채널 오디오의 경우 caps에 명시되지 않은 한 채널 레이아웃은 암시적으로 처리됩니다 ). 따라서 채널 레이아웃은 각 열거형 값이 스피커 위치를 나타내는 정수 열거형 값의 배열이 됩니다. GST_TYPE_LIST와 달리 배열의 값은 전체적으로 해석됩니다.
어떤 capabilities가 사용될까?
Capabilities (줄여서 caps)는 두 개의 apd 사이에 스트리밍되거나 하나의 pad (템플릿)가 지원하는 데이터 타입을 설명합니다. 이는 다양한 목적에 매우 유용합니다.
- Autoplugging: capabilities에 따라 pad에 연결할 element를 자동으로 찾습니다. 모든 autoplugger들은 이 방법을 사용합니다.
- Compatibility detection: 두 개의 pad가 연결되면 GStreamer는 두 개의 pad가 동일한 미디어 타입에 대해 이야기하는지 확인할 수 있습니다. 두 개의 pad를 연결하고 호환 여부를 확인하는 과정을 "caps negotiation"이라고 합니다.
- Metadata: 애플리케이션은 pad의 기능을 읽어 pad를 통해 스트리밍되는 미디어 타입에 대한 정보, 즉 현재 재생 중인 스트림에 대한 정보를 제공할 수 있습니다.
- Filtering: 애플리케이션은 두 개의 pad 간에 스트리밍할 수 있는 미디어 타입을 지원 스트림 유형의 특정 하위 집합으로 제한하기 위해 capabilities를 사용할 수 있습니다. 예를 들어, 애플리케이션은 두 개의 pad 간에 스트리밍되어야 하는 특정 (고정 또는 비고정) 비디오 크기를 설정하기 위해 "filtered caps"을 사용할 수 있습니다. 이 매뉴얼에서는 파이프라인에 데이터를 수동으로 추가하거나 제거하는 부분에서 filtered caps의 예제를 볼 수 있습니다. Capsfilter element를 파이프라인에 삽입하고 "caps" 속성을 설정하여 caps filtering을 수행할 수 있습니다. Caps filter는 일반적으로 converter element인 audioconvert, audioresample, videoconvert 또는 videoscale 뒤에 배치되어 해당 converter가 스트림의 특정 지점에서 데이터를 특정 출력 형식으로 변환하도록 강제합니다.
Metadata를 위한 capabilities 사용
Pad에는 일련의 capabilities (즉, 하나 이상)이 첨부될 수 있습니다. Capabilities (GstCaps)은 하나 이상의 GstStructure 배열로 표시되며, 각 GstStructure는 각 필드가 필드 이름 문자열 (예: "width")과 입력된 값 (예: G_TYPE_INT 또는 GST_TYPE_INT_RANGE)으로 구성된 필드 배열입니다.
Pad의 possible capabilities (즉. 일반적으로 gst-inspect에 표시된 pad 템플릿의 caps로 찾을 수 있습니다), pad의 allowed caps (peer pad의 possible caps에 따라 pad의 템플릿 caps이나 그 하위 집합과 동일할 수 있습니다), 그리고 마지막으로 negotiated caps (이는 스트림이나 버퍼의 정확한 형식을 설명하고 정확히 하나의 structure를 포함하며 range나 list과 같은 variable bits가 없습니다. 즉, 이들은 fixed caps 입니다.) 간에 명백한 차이가 있습니다.
한 structure의 개별 속성을 쿼리하여 capabilities 집합의 속성 값을 가져올 수 있습니다. gst_caps_get_structure()를 사용하여 caps에서 structure를 얻을 수 있고 gst_caps_get_size()를 사용하여 GstCaps의 structure의 수를 얻을 수 있습니다.
Cpas는 하나의 structure만 포함하는 경우 simple caps라고 하고, 하나의 structure만 포함하고 변수 필드 타입 (예: 가능한 values의 ranges 또는 lists)이 없는 경우 fixed caps라고 합니다. 다른 두 가지 특별한 타입의 caps에는 ANY caps와 empty caps가 있습니다.
다음은 fixed video caps 세트에서 width와 height를 추출하는 예입니다.
static void
read_video_props (GstCaps *caps)
{
gint width, height;
const GstStructure *str;
g_return_if_fail (gst_caps_is_fixed (caps));
str = gst_caps_get_structure (caps, 0);
if (!gst_structure_get_int (str, "width", &width) ||
!gst_structure_get_int (str, "height", &height)) {
g_print ("No width/height available\n");
return;
}
g_print ("The video size of this set of capabilities is %dx%d\n",
width, height);
}
Filtering을 위한 capabilities 생성
Pad의 미디어 타입을 설명하기 위해 주로 플러그인 내부에서 사용되는 capabilities와는 별도로, 어플리케이션 프로그래머는 종종 플러그인과 상호 작용하기 위해 capabilities에 대한 기본적인 이해가 필요합니다. 특히 filtered caps를 사용할 때 더욱 그렇습니다. Filtered caps 또는 fixation을 사용하는 경우 두 개의 pad 사이에서 스트리밍할 수 있는 미디어 타입을 지원되는 미디어 타입의 하위 집합으로 제한하게 됩니다. 파이프라인에서 capsfilter element를 사용하여 이 작업을 수행합니다. 이를 위해서는 자신만의 GstCap을 생성해야 합니다. 이를 수행하는 가장 쉬운 방법은 convenience function gst_caps_new_simple()을 사용하는 것입니다.
static gboolean
link_elements_with_filter (GstElement *element1, GstElement *element2)
{
gboolean link_ok;
GstCaps *caps;
caps = gst_caps_new_simple ("video/x-raw",
"format", G_TYPE_STRING, "I420",
"width", G_TYPE_INT, 384,
"height", G_TYPE_INT, 288,
"framerate", GST_TYPE_FRACTION, 25, 1,
NULL);
link_ok = gst_element_link_filtered (element1, element2, caps);
gst_caps_unref (caps);
if (!link_ok) {
g_warning ("Failed to link element1 and element2!");
}
return link_ok;
}
이렇게 하면 두 element 사이의 데이터 흐름이 특정 비디오 format, width, height, 그리고 framerate로 강제됩니다 (또는 관련 element의 컨텍스트에서 달성할 수 없는 경우 연결이 실패합니다). gst_element_link_filtered()를 사용하면 자동으로 capsfilter element가 생성되어 연결하려는 두 element 사이의 bin이나 파이프라인에 삽입된다는 점을 명심하세요 (만약 이 element들을 분리하고 싶을 때, capsfilter에서 두 element를 모두 분리해야 한다는 것을 기억하세요).
어떤 경우에는 두 pad 사이의 링크를 필터링하기 위해 보다 정교한 capabilities 세트를 만들고 싶을 수도 있습니다. 그러면 이 함수는 너무 단순하므로 gst_caps_new_full() 메서드를 사용하고 싶을 것입니다.
static gboolean
link_elements_with_filter (GstElement *element1, GstElement *element2)
{
gboolean link_ok;
GstCaps *caps;
caps = gst_caps_new_full (
gst_structure_new ("video/x-raw",
"width", G_TYPE_INT, 384,
"height", G_TYPE_INT, 288,
"framerate", GST_TYPE_FRACTION, 25, 1,
NULL),
gst_structure_new ("video/x-bayer",
"width", G_TYPE_INT, 384,
"height", G_TYPE_INT, 288,
"framerate", GST_TYPE_FRACTION, 25, 1,
NULL),
NULL);
link_ok = gst_element_link_filtered (element1, element2, caps);
gst_caps_unref (caps);
if (!link_ok) {
g_warning ("Failed to link element1 and element2!");
}
return link_ok;
}
GstStructure 및 GstCaps의 전체 API는 API 참조를 확인하세요.
Ghost pads
Ghost pads 없이 GstBin element를 시각화 (아래 그림)하는 것에서 보듯이, bin은 자체 패드를 갖지 않습니다 여기서 "ghost pads"가 작동합니다.
Ghost pad는 bin에 직접 액세스할 수 있는 bin의 일부 element에 있는 pad입니다. UNIX 파일 시스템의 심볼릭 링크와 비교해 보세요. Bin의 ghost pads를 사용하면 bin에도 pad가 있으며 코드의 다른 부분에서 element로 투명하게 사용할 수 있습니다.
Ghost pad를 사용한 GstBin element의 시각화 (위 그림)는 ghost pad를 표현한 것입니다. Element 1의 sink pad는 이제 bin의 pad이기도 합니다. Ghost pads는 다른 pad처럼 보이고 작동하기 때문에 일반 pad처럼 GstBin뿐만 아니라 모든 타입의 element에 추가할 수 있습니다.
Ghost pad는 gst_ghost_pad_new() 함수를 사용하여 생성됩니다:
#include <gst/gst.h>
int
main (int argc,
char *argv[])
{
GstElement *bin, *sink;
GstPad *pad;
/* init */
gst_init (&argc, &argv);
/* create element, add to bin */
sink = gst_element_factory_make ("fakesink", "sink");
bin = gst_bin_new ("mybin");
gst_bin_add (GST_BIN (bin), sink);
/* add ghostpad */
pad = gst_element_get_static_pad (sink, "sink");
gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));
gst_object_unref (GST_OBJECT (pad));
[..]
}
위의 예에서 bin에는 이제 pad가 있습니다. 해당 pad는 주어진 element의 "sink"라고 합니다. 이제부터는 bin을 sink element 대신 사용할 수 있습니다. 예를 들어 다른 element를 이 bin에 연결할 수 있습니다.
- 실제로는 upstream element (그림에서 이 element의 왼쪽)의 source pad에서 sink pad로 데이터가 흐르는 것에 대해 이의가 없습니다. 그러나 데이터는 항상 한 element의 source pad에서 다른 element의 sink pad로 흐릅니다.
원문: Pads and capabilities (gstreamer.freedesktop.org)
Pads and capabilities
Pads and capabilities As we have seen in Elements, the pads are the element's interface to the outside world. Data streams from one element's source pad to another element's sink pad. The specific type of media that the element can handle will be exposed b
gstreamer.freedesktop.org
'IT와 개발 > GStreamer Study' 카테고리의 다른 글
Your first application (0) | 2024.05.10 |
---|---|
Buffers and Events (0) | 2024.05.03 |
Bus (1) | 2024.04.19 |
Bins (1) | 2024.04.12 |
Elements (0) | 2024.04.05 |