이 챕터에서는 이전 챕터에서 배운 모든 내용을 요약합니다. 라이브러리 초기화, element 생성, element들을 파이프라인에 추가하고 이 파이프라인을 재생하는 등 간단한 GStreamer 애플리케이션의 모든 측면을 설명합니다. 이 모든 작업을 수행하면 간단한 Ogg/Vorbis 오디오 플레이어를 구축할 수 있습니다.
Hello world
우리는 간단한 Ogg/Vorbis command-line 오디오 플레이어인 첫 번째 애플리케이션을 만들 것입니다. 이를 위해 표준 GStreamer 구성 콤포넌트만 사용합니다. 플레이어는 command-line에 지정된 파일을 읽습니다. 그럼 시작하겠습니다.
우리는 GStreamer 초기화에서 애플리케이션에서 가장 먼저 해야 할 일은 gst_init()를 호출하여 GStreamer를 초기화하는 것임을 배웠습니다. 또한 모든 함수 이름과 객체가 올바르게 정의되도록 애플리케이션에 gst/gst.h가 포함되어 있는지 확인하세요. 그렇게 하려면 #include <gst/gst.h>를 사용하세요.
다음으로, gst_element_factory_make()를 사용하여 다양한 element를 생성하고 싶을 것입니다. Ogg/Vorbis 오디오 플레이어의 경우 디스크에서 파일을 읽는 source element가 필요합니다. GStreamer는 "filesrc"라는 이름으로 이 element를 포함합니다. 다음으로, 파일을 구문 분석하고 raw 오디오로 디코딩할 무언가가 필요합니다. GStreamer에는 이를 위한 두 가지 element가 있습니다. 첫 번째 element는 Ogg 스트림을 elementary 스트림 (비디오, 오디오)으로 구문 분석하는 "oggdemux"라고 합니다. 두 번째는 Vorbis 오디오 디코더로, 편의상 "vorbisdec"이라고 불립니다. "oggdemux"는 각 elementary 스트림에 대한 dynamic pad를 생성하므로 Ogg 디먹서와 Vorbis 디코더 element를 연결하려면 Dynamic (또는 sometimes) pad에서 배운 것처럼 "oggdemux" element에서 "pad-added" 이벤트 핸들러를 설정해야 합니다. 마지막으로 오디오 출력 element가 필요하기 때문에 오디오 장치를 자동으로 감지하는 "autoaudiosink"를 사용합니다.
마지막으로 남은 작업은 모든 element를 컨테이너 element인 GstPipeline에 추가하고 전체 노래가 재생될 때까지 기다리는 것입니다. 우리는 이전에 Bins의 container bin에 element를 추가하는 방법을 배웠고 Element States에서 element 상태에 대해 배웠습니다. 또한 오류를 검색하고 스트림 끝을 감지할 수 있도록 메시지 핸들러를 파이프라인 bus에 연결합니다.
이제 첫 번째 오디오 플레이어를 얻기 위해 모든 코드를 함께 추가해 보겠습니다.
#include <gst/gst.h>
#include <glib.h>
static gboolean
bus_call (GstBus *bus,
GstMessage *msg,
gpointer data)
{
GMainLoop *loop = (GMainLoop *) data;
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_EOS:
g_print ("End of stream\n");
g_main_loop_quit (loop);
break;
case GST_MESSAGE_ERROR: {
gchar *debug;
GError *error;
gst_message_parse_error (msg, &error, &debug);
g_free (debug);
g_printerr ("Error: %s\n", error->message);
g_error_free (error);
g_main_loop_quit (loop);
break;
}
default:
break;
}
return TRUE;
}
static void
on_pad_added (GstElement *element,
GstPad *pad,
gpointer data)
{
GstPad *sinkpad;
GstElement *decoder = (GstElement *) data;
/* We can now link this pad with the vorbis-decoder sink pad */
g_print ("Dynamic pad created, linking demuxer/decoder\n");
sinkpad = gst_element_get_static_pad (decoder, "sink");
gst_pad_link (pad, sinkpad);
gst_object_unref (sinkpad);
}
int
main (int argc,
char *argv[])
{
GMainLoop *loop;
GstElement *pipeline, *source, *demuxer, *decoder, *conv, *sink;
GstBus *bus;
guint bus_watch_id;
/* Initialisation */
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
/* Check input arguments */
if (argc != 2) {
g_printerr ("Usage: %s <Ogg/Vorbis filename>\n", argv[0]);
return -1;
}
/* Create gstreamer elements */
pipeline = gst_pipeline_new ("audio-player");
source = gst_element_factory_make ("filesrc", "file-source");
demuxer = gst_element_factory_make ("oggdemux", "ogg-demuxer");
decoder = gst_element_factory_make ("vorbisdec", "vorbis-decoder");
conv = gst_element_factory_make ("audioconvert", "converter");
sink = gst_element_factory_make ("autoaudiosink", "audio-output");
if (!pipeline || !source || !demuxer || !decoder || !conv || !sink) {
g_printerr ("One element could not be created. Exiting.\n");
return -1;
}
/* Set up the pipeline */
/* we set the input filename to the source element */
g_object_set (G_OBJECT (source), "location", argv[1], NULL);
/* we add a message handler */
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
gst_object_unref (bus);
/* we add all elements into the pipeline */
/* file-source | ogg-demuxer | vorbis-decoder | converter | alsa-output */
gst_bin_add_many (GST_BIN (pipeline),
source, demuxer, decoder, conv, sink, NULL);
/* we link the elements together */
/* file-source -> ogg-demuxer ~> vorbis-decoder -> converter -> alsa-output */
gst_element_link (source, demuxer);
gst_element_link_many (decoder, conv, sink, NULL);
g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), decoder);
/* note that the demuxer will be linked to the decoder dynamically.
The reason is that Ogg may contain various streams (for example
audio and video). The source pad(s) will be created at run time,
by the demuxer when it detects the amount and nature of streams.
Therefore we connect a callback function which will be executed
when the "pad-added" is emitted.*/
/* Set the pipeline to "playing" state*/
g_print ("Now playing: %s\n", argv[1]);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
/* Iterate */
g_print ("Running...\n");
g_main_loop_run (loop);
/* Out of the main loop, clean up nicely */
g_print ("Returned, stopping playback\n");
gst_element_set_state (pipeline, GST_STATE_NULL);
g_print ("Deleting pipeline\n");
gst_object_unref (GST_OBJECT (pipeline));
g_source_remove (bus_watch_id);
g_main_loop_unref (loop);
return 0;
}
이제 완전한 파이프라인이 생성되었습니다. 파이프라인을 다음과 같이 시각화할 수 있습니다.
helloworld.c 컴파일 및 실행
helloworld 예제를 컴파일하려면 다음을 사용하세요.
gcc -Wall helloworld.c -o helloworld $(pkg-config --cflags --libs gstreamer-1.0)
GStreamer는 pkg-config를 사용하여 이 애플리케이션을 컴파일하는데 필요한 컴파일러 및 링커 플래그를 가져옵니다.
비표준 설치를 실행하는 경우 (즉, 미리 빌드된 패키지를 사용하는 대신 소스에서 GStreamer를 직접 설치한 경우) PKG_CONFIG_PATH 환경 변수가 올바른 위치 ($libdir/pkgconfig)로 설정되어 있는지 확인하세요.
GStreamer 개발 환경 (예: gst-env)을 사용하는 경우는 드물지만 다음과 같이 libtool을 사용하여 hello world 프로그램을 빌드해야 합니다.
libtool --mode=link gcc -Wall helloworld.c -o helloworld $(pkg-config --cflags --libs gstreamer-1.0)
./helloworld file.ogg를 사용하여 이 예제 애플리케이션을 실행할 수 있습니다. file.ogg를 즐겨 사용하는 Ogg/Vorbis 파일로 대체하세요.
결론
이것으로 첫 번째 예제를 마칩니다. 보시다시피 파이프라인 설정은 매우 낮은 수준이지만 강력합니다. 이 매뉴얼의 뒷부분에서 더 높은 수준의 인터페이스를 사용하여 더 적은 노력으로 더 강력한 미디어 플레이어를 만드는 방법을 살펴보게 될 것입니다. 우리는 GStreamer 애플리케이션을 위한 상위 레벨 인터페이스에서 모든 것을 논의할 것입니다. 그러나 먼저 고급 GStreamer 내부에 대해 더 깊이 살펴보겠습니다.
예제를 보면 "filesrc" 요소를 네트워크에서 데이터를 읽는 다른 요소나 데스크탑 환경과 더 잘 통합되는 다른 데이터 source element로 매우 쉽게 대체할 수 있다는 것이 분명해졌습니다. 또한 다른 디코더와 파서/디먹서를 사용하여 다른 미디어 유형을 지원할 수 있습니다. Linux가 아닌 Mac OS X, Windows 또는 FreeBSD를 실행하는 경우 다른 오디오 sink를 사용할 수 있습니다. 또는 대신 filesink를 사용하여 오디오 파일을 재생하는 대신 디스크에 쓸 수 있습니다. 오디오 카드 소스를 사용하면 재생 대신 오디오 캡처를 수행할 수도 있습니다. 이 모든 것은 가장 큰 장점인 GStreamer element의 재사용성을 보여줍니다.
원문: Your first application (gstreamer.freedesktop.org)
Your first application
Your first application This chapter will summarize everything you've learned in the previous chapters. It describes all aspects of a simple GStreamer application, including initializing libraries, creating elements, packing elements together in a pipeline
gstreamer.freedesktop.org
'IT와 개발 > GStreamer Study' 카테고리의 다른 글
Metadata (91) | 2024.05.24 |
---|---|
Position tracking and seeking (0) | 2024.05.17 |
Buffers and Events (0) | 2024.05.03 |
Pads and capabilities (1) | 2024.04.26 |
Bus (1) | 2024.04.19 |