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);
}
전체 소스는 파일로 첨부하였습니다.
참고
- http://stackoverflow.com/questions/32233370/gstreamer-1-0-rtspsrc-to-rtph264depay-cannot-link
- https://gstreamer.freedesktop.org/documentation/application-development/basics/pads.html#dynamic-or-sometimes-pads
'GStreamer' 카테고리의 다른 글
[GStreamer] Push, Pull 방식 (2) | 2017.04.05 |
---|---|
[GStreamer] RTSP의 H264 영상 Dump 방법 (1) | 2017.03.29 |
[GStreamer] 디버깅 로그 출력하기 (0) | 2017.03.29 |
[GStreamer] h264 profile 확인하는 방법 (0) | 2017.03.27 |
[GStreamer] 윈도우 Visual Studio 개발 환경 설정 (2) | 2017.03.06 |