2017-03-21 1 views
1

저는 Gstreamer의 초보자입니다. UDP 카메라에서 프레임을 가져와 cv::Mat (OpenCV)으로 변환해야합니다.C++의 Qt에서 Gstreamer와 관련된 문제 : 흐름 오류

gst-launch-1.0 v4l2src device=/dev/video0 ! \ 
    h264parse ! rtph264pay ! udpsink host=XXX.XXX.XXX.XXX port=5000 

을 그리고 다른 터미널에서이 같은 스트림을 얻을 수있다 (그리고 그것은 작동) : 나는 이런 식으로 내 카메라 스트림을 실행

gst-launch-1.0 udpsrc port=5000 caps='application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264' ! \ 
rtph264depay ! avdec_h264 ! autovideosink 

그래서 내 C에서 ++ 코드는 여기 ++ 코드 내 C이다 :

GstFlowReturn new_preroll(GstAppSink *appsink, gpointer data) { g_print ("Got preroll!\n"); return GST_FLOW_OK; } GstFlowReturn new_sample(GstAppSink *appsink, gpointer data) { static int framecount = 0; framecount++; GstSample *sample = gst_app_sink_pull_sample(appsink); GstCaps *caps = gst_sample_get_caps(sample); GstBuffer *buffer = gst_sample_get_buffer(sample); const GstStructure *info = gst_sample_get_info(sample); // ---- Read frame and convert to opencv format --------------- GstMapInfo map; gst_buffer_map (buffer, &map, GST_MAP_READ); // convert gstreamer data to OpenCV Mat, you could actually // resolve height/width from caps... Mat frame(Size(320, 240), CV_8UC3, (char*)map.data, Mat::AUTO_STEP); int frameSize = map.size; // TODO: synchronize this.... frameQueue.push_back(frame); gst_buffer_unmap(buffer, &map); // ------------------------------------------------------------ // print dot every 30 frames if (framecount%30 == 0) { g_print ("."); } // show caps on first frame if (framecount == 1) { g_print ("%s\n", gst_caps_to_string(caps)); } gst_sample_unref (sample); return GST_FLOW_OK; } static gboolean my_bus_callback (GstBus *bus, GstMessage *message, gpointer data) { g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message)); switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_ERROR: { GError *err; gchar *debug; gst_message_parse_error (message, &err, &debug); g_print ("Error: %s\n", err->message); g_error_free (err); g_free (debug); break; } case GST_MESSAGE_EOS: /* end-of-stream */ break; default: /* unhandled message */ break; } /* we want to be notified again the next time there is a message * on the bus, so returning TRUE (FALSE means we want to stop watching * for messages on the bus and our callback should not be called again) */ return TRUE; } int main (int argc, char *argv[]) { GError *error = NULL; gst_init (&argc, &argv); gchar *descr = g_strdup( "udpsrc port=5000 ! " "caps=application/x-rtp, media=(string)video, clock-rate=(int)9000, encoding-name=(string)H264 ! " "rtph264depay ! " "avdec_h264 ! " "videoconvert ! " "appsink name=sink " ); GstElement *pipeline = gst_parse_launch (descr, &error); if (pipeline== NULL) { g_print ("could not construct pipeline: %s\n", error->message); g_error_free (error); exit (-1); } /* get sink */ GstElement *sink = gst_bin_get_by_name (GST_BIN (pipeline), "sink"); gst_app_sink_set_emit_signals((GstAppSink*)sink, true); gst_app_sink_set_drop((GstAppSink*)sink, true); gst_app_sink_set_max_buffers((GstAppSink*)sink, 1); GstAppSinkCallbacks callbacks = { NULL, new_preroll, new_sample }; gst_app_sink_set_callbacks (GST_APP_SINK(sink), &callbacks, NULL, NULL); GstBus *bus; guint bus_watch_id; bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); bus_watch_id = gst_bus_add_watch (bus, my_bus_callback, NULL); gst_object_unref (bus); GstStateChangeReturn test=gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); qDebug() <<test<< " this is the test"; namedWindow("edges",1); while(1) { g_main_iteration(false); // TODO: synchronize... if (frameQueue.size() >10) { // this lags pretty badly even when grabbing frames from webcam Mat frame = frameQueue.front(); imshow("edges", frame); cv::waitKey(30); frameQueue.clear(); } } gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); gst_object_unref (GST_OBJECT (pipeline)); return 0; }

그리고 나는 오류 얻을 :

Error: Internal data flow error.

내 파이프 라인 선언에서 온 것 같지만 잘못된 점은 찾을 수 없습니다. 제안 사항이 있으십니까?

+0

Qt 태그는 관련성이 없어 제거하라고했습니다. 코드가 정확하고 그것이 일어날 수있는 이유는 다음과 같습니다. 코드가 실패한 시스템에서 모든 환경이 올바른지 확인하려고합니다. – AlexanderVX

답변

1

udpsrc port=5000 다음에 !이 있습니다. 그 하나는 원래 파이프 라인에 존재하지 않습니다. 나는 더 이상 체크하지 않았으며 아마도 파이프 라인을 프린트하고 원하는 것이 있다면 두번 체크한다.

+0

고마워요! 그게 문제 였어! 멍청한 실수 . – Maxence

+0

이제 gstreamer 파이프 라인에서 videoconvert에 문제가 있습니다 ... 이미지를 RGB 형식으로 변환해야합니다. gchar * descr = g_strdup ( "udpsrc port = 5000" "caps = \"application/x-rtp \ "!" "rtph264depay!" "avdec_h264!" "decodebin!" "videoconvert!" "비디오/X-원시 포맷 = (문자열) RGB!" "videoconvert!" "appsink NAME = sink "그러나 이미지가 변형되어 C와 마찬가지로 동일한 명령으로 터미널에 표시됩니다. – Maxence

+0

왜 두 개의 videoconvert 요소가 있는지 확실하지 않습니다. 여기에 decodebin의 목적도 아무 것도없는 것처럼 보입니다. 그러나 실제 문제는 데이터가 RGB에 어떻게 저장되는지 오해 인 것 같습니다. 그것을 어떻게 보간 하는가? 그러나 그것은 내가 가진 모든 것이 "작동하지 않는다"는 가정에 불과합니다. –