GStreamer

[GStreamer] Pad-added Signal

behonestar 2017. 3. 6. 11:50

GStreamer로 RTSP 영상을 화면에 출력하기 위해 이렇게 작성하였습니다.


int main(int argc, char *argv[]) {

GstElement *pipeline, *source, *demux, *parse, *filter, *decodebin, *sink;

GstBus *bus;

GstMessage *msg;

GstStateChangeReturn ret;


gst_init (&argc, &argv);


// Pipeline과 Element 생성

pipeline = gst_pipeline_new ("video player");

source = gst_element_factory_make("rtspsrc", "source");

demux = gst_element_factory_make("rtph264depay", "depayl");

parse = gst_element_factory_make("h264parse", "parse");

filter = gst_element_factory_make("capsfilter", "filter");

decodebin = gst_element_factory_make ("openh264dec", "decode");

sink = gst_element_factory_make("autovideosink", "sink");


if (!pipeline || !source || !demux || !parse || !filter || !decodebin || !sink) {

g_printerr ("Not all elements could be created.\n");

return -1;

}


g_object_set (source, "location", "rtsp://mpv.cdn3.bigCDN.com:554/bigCDN/definst/mp4:bigbuckbunnyiphone_400.mp4", NULL);


// Pipeline에 Element 추가

gst_bin_add_many (GST_BIN (pipeline), source, demux, parse, filter, decodebin, sink, NULL);

// 각 Element들을 연결

if (gst_element_link_many (source, demux, parse, filter, decodebin, sink, NULL) != TRUE) {

g_printerr ("Elements could not be linked.\n");

gst_object_unref (pipeline);

return -1;

}

// RTSP Play

ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);


//... 생략 ...

}


그런데 Elements could not be linked 오류로 빠지네요. 그 이유는 바로 rtspsrc 플러그인의 Pad 타입이 'Sometimes'이기 때문입니다. 


$ gst-inspect-1.0 rtspsrc


Pad Templates:

  SRC template: 'stream_%u'

    Availability: Sometimes

    Capabilities:

      application/x-rtp

      application/x-rdt


즉, source 엘리먼트는 Pad가 없는 상태로 생성됩니다. Pad는 RTSP가 PLAY 될 때 추가됩니다. 그래서 source와 demux 엘리먼트 간 연결은 PLAY 이후에만 가능합니다.




source 엘리먼트에 Pad가 추가되는 것을 감지하여 demux 엘리먼트와 연결되도록 하려면 "pad-added" 시그널을 받아서 처리하면 됩니다.


int main(int argc, char *argv[]) {


// ...생략...


g_signal_connect_object(source, "pad-added", G_CALLBACK(on_pad_added), demux, G_CONNECT_AFTER);


ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);


// ...생략...

}


콜백되는 on_pad_added 함수에서는 인자로 전달된 demux 엘리먼트의 sink pad와 source의 src pad를 연결합니다.


static void on_pad_added (GstElement *element, GstPad *pad, gpointer data) {

GstPad *sinkpad;

GstElement *demux = (GstElement *) data;


sinkpad = gst_element_get_static_pad (demux, "sink");

gst_pad_link (pad, sinkpad);

gst_object_unref (sinkpad);

}




전체 소스는 파일로 첨부하였습니다.

rtsp_play.cpp



참고