SPRING :: NOTE
[GStreamer] TCP/IP로 Cam Streaming 본문
반응형
on_pad_added Function 추가
static void on_pad_added(GstElement *element, GstPad *pad, gpointer data)
{
TRACE("Pad added");
GstElement *decodebin = static_cast<GstElement*>(data);
GstPad *sink_pad = gst_element_get_static_pad(decodebin, "sink");
if (gst_pad_is_linked(sink_pad)) {
TRACE("Already linked ignore1");
return;
}
auto ret = gst_pad_link(pad, sink_pad);
TRACE("Link pad" + GST_PAD_LINK_FAILED(ret));
}
on_decoded_pad_added Function 추가
static void on_decoded_pad_added(GstElement *element, GstPad *pad, gpointer data)
{
TRACE("Decoded Pad added");
GstElement *decodebin = static_cast<GstElement*>(data);
GstPad *sink_pad = gst_element_get_static_pad(decodebin, "sink");
if (gst_pad_is_linked(sink_pad)) {
TRACE("Already linked ignore2");
return;
}
auto ret = gst_pad_link(pad, sink_pad);
TRACE("Link pad 2, %s", GST_PAD_LINK_FAILED(ret));
}
Thread에서 아래 코드 추가(실제 스트리밍 코드)
들어오는 코덱에 맞춰 Decod 또는 parsing부를 변경한다.
while (TRUE)
{
Sleep(1000);
// Initialize GStreamer
gst_init(0, NULL);
int cnt = 0;
CWnd* viewer = pDlg->GetDlgItem(IDC_GST_VIEWER);
HANDLE m_WindowHandle = viewer->GetSafeHwnd();
GstStateChangeReturn ret;
GstElement *tsdemux;
GstElement *h264parse;
GstElement *avdec_h264;
GstElement *sink;
GstElement *zoom;
GMainLoop *loop;
GstBus *bus;
GstMessage *msg;
CString strTemp;
// ## TEST TYPE ,,, TRUE : STREAMING, FALSE : FILE
boolean gstType = true;
loop = g_main_loop_new(NULL, FALSE);
tsdemux = gst_element_factory_make("tsdemux", "tsdemux");
h264parse = gst_element_factory_make("h264parse", "h264parse");
avdec_h264 = gst_element_factory_make("avdec_h264", "h264decoder");
sink = gst_element_factory_make("d3dvideosink", "videosink"); // glimagesink, d3dvideosink
pDlg->m_pPipeline = gst_pipeline_new(NULL);
if (!gstType)
{
//WEB STREAMING
pDlg->m_pPlaybin = gst_element_factory_make("playbin", NULL);
gst_bin_add(GST_BIN(pDlg->m_pPipeline), pDlg->m_pPlaybin);
g_object_set(G_OBJECT(pDlg->m_pPlaybin), "uri", "file:///C:/Users/RAYZIE/kkk/test.mp4", NULL);
//g_object_set(G_OBJECT(m_pPlaybin), "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL);
}
else
{
//TCP/IP
pDlg->m_pPlaybin = gst_element_factory_make("tcpserversrc", NULL);
gst_bin_add(GST_BIN(pDlg->m_pPipeline), pDlg->m_pPlaybin);
//1280-720
g_object_set(G_OBJECT(pDlg->m_pPlaybin), "host", "192.168.137.1", "port", 5000, "sync", false, NULL);
g_object_set(G_OBJECT(sink), "sync", FALSE, NULL);
gst_bin_add_many(GST_BIN(pDlg->m_pPipeline), pDlg->m_pPlaybin, tsdemux, h264parse, avdec_h264, sink, nullptr);
gst_element_link(pDlg->m_pPlaybin, tsdemux);
gst_element_link_many(h264parse, avdec_h264, sink, NULL);
g_signal_connect(tsdemux, "pad-added", G_CALLBACK(on_pad_added), h264parse);
g_signal_connect(h264parse, "pad-added", G_CALLBACK(on_pad_added), avdec_h264);
g_signal_connect(pDlg->m_pPlaybin, "pad-added", G_CALLBACK(on_decoded_pad_added), sink);
}
VideoCapture cap;
if (m_WindowHandle != nullptr)
gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(sink), (guintptr)m_WindowHandle);
//cap = VideoCapture(pDlg->m_pPlaybin, CAP_GSTREAMER);
ret = gst_element_set_state(pDlg->m_pPipeline, GST_STATE_PLAYING);
// Gstreamer Playing
if (ret == GST_STATE_CHANGE_FAILURE)
{
cnt++;
TRACE("Unable to set the pipeline to the playing state.\n");
strTemp.Format("TCP/IP 접속 실패, IP 주소를 확인하세요., Count = %d\n", cnt);
pDlg->m_GstView.SetWindowTextA(strTemp);
gst_object_unref(pDlg->m_pPipeline);
continue;
}
else
{
// Wait until error or EOS
bus = gst_element_get_bus(pDlg->m_pPipeline);
msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_EOS);
// Free resources
if (msg != NULL)
gst_message_unref(msg);
gst_object_unref(bus);
gst_element_set_state(pDlg->m_pPipeline, GST_STATE_NULL);
gst_object_unref(pDlg->m_pPipeline);
//strTemp.Format("스트리밍 실패, 무인기의 웨이브 모듈 접속이 원활하지 않음, Reconnecting..., Count = %d\n", cnt);
//pDlg->m_GstView.SetWindowTextA(strTemp);
cnt++;
continue;
}
TRACE("Running\n");
g_main_loop_run(loop);
// Clean up after execution of main loop
gst_element_set_state(pDlg->m_pPipeline, GST_STATE_NULL);
TRACE("Quitting\n");
g_object_unref(G_OBJECT(pDlg->m_pPipeline));
// g_source_remove(bus_watch_id);
g_main_loop_unref(loop);
}
sink 부분은 linux, windows 등 운영체제에서 지원하는 sink가 다 다르기때문에 이는 gstreamer 공식 document를 참조하자.
반응형
'Development Language > C · C++ · MFC' 카테고리의 다른 글
[C++/MFC] libvlc(VLC library)를 이용하여 RTP over RTSP 옵션 추가 (0) | 2019.07.16 |
---|---|
[OpenCV] cv::mat으로 받은 데이터 Controller에 출력 (0) | 2019.07.04 |
[MFC] Application Close Code(프로그램 종료 코드) (0) | 2018.12.11 |
[C++] FTP Upload/Download 구현 클래스(매우 유용) (0) | 2018.12.03 |
[MFC] 프로그램 시작 시, Application 전체화면으로 시작 (0) | 2018.12.03 |
Comments