'Tutorial'에 해당되는 글 1건

  1. 2026.04.16 [GStreamer] Tutorial 튜토리얼 정리
반응형

Basic tutorial 1: Hello world!

 

#include <gst/gst.h>

int main(int argc, char* argv[])
{
	GstElement* pipeline;
	GstBus* bus;
	GstMessage* msg;

	/* Initialize GStreamer */
	gst_init(&argc, &argv);

	/* Build the pipeline */
	pipeline = gst_parse_launch("playbin uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm", NULL);

	/* Start playing */
	gst_element_set_state(pipeline, GST_STATE_PLAYING);

	/* Wait until error or EOS */
	bus = gst_element_get_bus(pipeline);
	msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, (GstMessageType)(GST_MESSAGE_ERROR | GST_MESSAGE_EOS));
	// GST_MESSAGE_ERROR, GST_MESSAGE_EOS 는 GstMessageType 열거형의 멤버로, 각각 오류 메시지와 End Of Stream 메시지를 나타낸다.
	// GstMessageType으로 형변환 해야한다.
	// gst_bus_timed_pop_filtered 함수는 버스에서 지정된 유형의 메시지를 기다리고, 해당 메시지가 도착하면 반환한다.
	// GST_CLOCK_TIME_NONE는 무한 대기 시간을 의미한다. 따라서 이 코드는 오류나 EOS 메시지가 도착할 때까지 기다린다.

	/* See next tutorial for proper error message handling/parsing */
	if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) {
		g_printerr("An error occurred! Re-run with the GST_DEBUG=*:WARN environment variable set for more details.\n");
	}

	/* Free resources */
	gst_message_unref(msg);
	gst_object_unref(bus);
	gst_element_set_state(pipeline, GST_STATE_NULL);
	gst_object_unref(pipeline);

	return 0;
}

 

playbin uri에 IP 카메라 스트리밍 주소(RTSP)를 넣어도 잘 작동하지만 파이프라인 최적화가 되지 않아 반응이 느리다.

pipeline = gst_parse_launch("playbin uri=rtsp://admin:admin@192.168.0.92:554/stream1", NULL);

 

 

Basic tutorial 12: Streaming

#include <gst/gst.h>
#include <string.h>

typedef struct _CustomData {
	gboolean is_live;
	GstElement* pipeline;
	GMainLoop* loop;
} CustomData;

static void cb_message(GstBus* bus, GstMessage* msg, CustomData* data) {
	switch (GST_MESSAGE_TYPE(msg)) {
	case GST_MESSAGE_ERROR: {
		GError* err = NULL;
		gchar* debug = NULL;

		gst_message_parse_error(msg, &err, &debug);
		g_print("Error: %s\n", err->message);
		g_error_free(err);
		g_free(debug);

		gst_element_set_state(data->pipeline, GST_STATE_READY);
		g_main_loop_quit(data->loop);
		break;
	} // case 내부에서 변수를 선언하고 초기화할 때는 중괄호로 감싸줘야 한다.

	case GST_MESSAGE_EOS:
		/* end-of-stream */
		gst_element_set_state(data->pipeline, GST_STATE_READY);
		g_main_loop_quit(data->loop);
		break;

	case GST_MESSAGE_BUFFERING: {
		gint percent = 0;

		/* If the stream is live, we do not care about buffering. */
		if (data->is_live)
			break;

		gst_message_parse_buffering(msg, &percent);
		g_print("Buffering (%3d%%)\r", percent);
		/* Wait until buffering is complete before start/resume playing */
		if (percent < 100)
			gst_element_set_state(data->pipeline, GST_STATE_PAUSED);
		else
			gst_element_set_state(data->pipeline, GST_STATE_PLAYING);
		break;
	} // case 내부에서 변수를 선언하고 초기화할 때는 중괄호로 감싸줘야 한다.

	case GST_MESSAGE_CLOCK_LOST:
		/* Get a new clock */
		gst_element_set_state(data->pipeline, GST_STATE_PAUSED);
		gst_element_set_state(data->pipeline, GST_STATE_PLAYING);
		break;
        // GST_MESSAGE_CLOCK_LOST: The current clock, as selected by the pipeline,
        // became unusable. The pipeline will select a new clock on the next PLAYING
        // state change.        
        // GStreamer에서 GST_MESSAGE_CLOCK_LOST 메시지는 파이프라인에서 현재 사용 중인
        // 클럭(Clock)을 더 이상 사용할 수 없게 되었을 때 발생한다. 이 메시지는 주로 다음과
        // 같은 상황에서 나타난다.
        // - 현재 클럭 제공자 유실: 파이프라인의 시간 기준(Master Clock)을 제공하던 요소
        // (예: 오디오 싱크, 오디오 소스 등)가 더 이상 클럭을 제공할 수 없을 때 발생.
        // - 새로운 소스 추가/변경: RTSP 스트림 추가 등 동적으로 파이프라인 소스가 변경되면서
        // 기존 클럭이 유효하지 않게 된 경우.
        // - 재생 상태 변경: 파이프라인이 재생(PLAYING) 상태에서 멈추거나 플러시(Flush)된 후
        // 다시 시작할 때 클럭을 재선택해야 하는 상황.

	default:
		/* Unhandled message */
		break;
	}
}

int main(int argc, char* argv[]) {
	GstElement* pipeline;
	GstBus* bus;
	GstStateChangeReturn ret;
	GMainLoop* main_loop;
	CustomData data;

	/* Initialize GStreamer */
	gst_init(&argc, &argv);

	/* Initialize our data structure */
	memset(&data, 0, sizeof(data));

	/* Build the pipeline */
	pipeline = gst_parse_launch("playbin uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm", NULL);
	//pipeline = gst_parse_launch("playbin uri=rtsp://admin:admin@192.168.0.92:554/stream1", NULL); // IP 카메라 스트림
	bus = gst_element_get_bus(pipeline);

	/* Start playing */
	ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
	if (ret == GST_STATE_CHANGE_FAILURE) {
		// GST_STATE_CHANGE_FAILURE (0) – the state change failed
		g_printerr("Unable to set the pipeline to the playing state.\n");
		gst_object_unref(pipeline);
		return -1;
	}
	else if (ret == GST_STATE_CHANGE_NO_PREROLL) {
		// GST_STATE_CHANGE_NO_PREROLL (3) – the state change succeeded but the element cannot produce data in GST_STATE_PAUSED.
		// This typically happens with live sources.
		// IP 카메라 스트림과 같이 라이브 스트림을 재생할 때는 이 상태가 반환될 수 있다.
		data.is_live = TRUE;
	}

	main_loop = g_main_loop_new(NULL, FALSE);
	data.loop = main_loop;
	data.pipeline = pipeline;

	gst_bus_add_signal_watch(bus);
	g_signal_connect(bus, "message", G_CALLBACK(cb_message), &data);

	g_main_loop_run(main_loop);

	/* Free resources */
	g_main_loop_unref(main_loop);
	gst_object_unref(bus);
	gst_element_set_state(pipeline, GST_STATE_NULL);
	gst_object_unref(pipeline);

	return 0;
}

 

 

 

 

 

 

 

 

 

반응형
Posted by J-sean
: