Dynamic pipelines

이상문·2021년 8월 31일
0

gstreamer

목록 보기
4/5

pad

소스 원소

필터 원소

싱크 원소

디먹서 원소

각 원소에는 pad라는 구성 요소를 가지고 있다.
소스에는 src pad, 싱크에는 sink pad, 필터의 경우에는 src 와 sink pad를 동시에 가지고 있는 경우이다.
demuxer의 경우에는 여러 미디어를 분리해내서 출력하기 때문에 여러 개의 src pad가 존재할 수 있다. 그리고, 입력을 파싱하는 과정에서 몇 개의 pad가 존재하는지 알 수 있기 때문에 생성할 때 pad를 결정할 수 없다.
결정할 수 있는 시점에서 동적으로 파이프라인을 구성하는 방법이 필요하다.

/* Create the elements */
data.source = gst_element_factory_make ("uridecodebin", "source");
data.convert = gst_element_factory_make ("audioconvert", "convert");
data.resample = gst_element_factory_make ("audioresample", "resample");
data.sink = gst_element_factory_make ("autoaudiosink", "sink");

uridecodebin 은 디벅서를 포함하고 있기 때문에 source pad를 바로 사용할 수는 없다.

if (!gst_element_link_many (data.convert, data.resample, data.sink, NULL)) {
  g_printerr ("Elements could not be linked.\n");
  gst_object_unref (data.pipeline);
  return -1;
}

원소들을 연결하지만, 소스와는 연결하지 않는다.

/* Set the URI to play */
g_object_set (data.source, "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL);

소스의 프로퍼티를 지정한다.

Signals

/* Connect to the pad-added signal */
g_signal_connect (data.source, "pad-added", G_CALLBACK (pad_added_handler), &data);

uridecodebinpad-added 신호를 발생시킨다. 이 신호에 대해 pad_added_handler 라는 콜백 함수를 등록하여 처리한다.

콜백 함수

static void pad_added_handler (GstElement *src, GstPad *new_pad, CustomData *data) {

new_pad 는 소스 원소에 추가되는 pad이다. 콜백 함수 등록할 때 함께 설정해준 데이터(포인터)가 함께 인자로 넘어온다.

GstPad *sink_pad = gst_element_get_static_pad (data->convert, "sink");

소스 원소의 pad와 연결할 싱크 pad를 얻어와야 한다. 연결될 싱크 pad는 audioconvert 원소에 포함되어 있다.

/* If our converter is already linked, we have nothing to do here */
if (gst_pad_is_linked (sink_pad)) {
  g_print ("We are already linked. Ignoring.\n");
  goto exit;
}

이미 연결되어 있는 경우는 연결하지 않는다.

/* Check the new pad's type */
new_pad_caps = gst_pad_get_current_caps (new_pad, NULL);
new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);
new_pad_type = gst_structure_get_name (new_pad_struct);
if (!g_str_has_prefix (new_pad_type, "audio/x-raw")) {
  g_print ("It has type '%s' which is not raw audio. Ignoring.\n", new_pad_type);
  goto exit;
}

uridecodebin 은 여러 pad를 생성할 수 있으며, 각각에 대해 콜백 함수가 호출된다. pad의 정보를 통해 한 번만 연결한다.

최종적으로 얻게 되는 prefix가 audio/x-raw 가 아니라면 오디오가 아니므로, 처리하지 않는다.

/* Attempt the link */
ret = gst_pad_link (new_pad, sink_pad);
if (GST_PAD_LINK_FAILED (ret)) {
  g_print ("Type is '%s' but link failed.\n", new_pad_type);
} else {
  g_print ("Link succeeded (type '%s').\n", new_pad_type);
}

gst_element_link() 와 유사하게 두 개의 pad를 연결한다.

GStreamer States

NULL, READY, PAUSED, PLAYING, 4가지의 상태가 있다.
상태 변경은 뛰어 넘어서 이동할 수 없다. 즉, NULL에서 PLAYING으로 넘어갈 수는 없다.

case GST_MESSAGE_STATE_CHANGED:
  /* We are only interested in state-changed messages from the pipeline */
  if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data.pipeline)) {
    GstState old_state, new_state, pending_state;
    gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
    g_print ("Pipeline state changed from %s to %s:\n",
        gst_element_state_get_name (old_state), gst_element_state_get_name (new_state));
  }
  break;

상태가 변경될 때, 확인할 수 있는 메시지를 남긴다.

profile
프로그래밍을 좋아하는 평범한 개발자입니다.

0개의 댓글