SPRING :: NOTE

[GStreamer] TCP/IP로 Cam Streaming 본문

Development Language/C · C++ · MFC

[GStreamer] TCP/IP로 Cam Streaming

RAYZIE 2019. 6. 26. 16:29
반응형

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를 참조하자.

반응형
Comments