2016-11-07 1 views
8

별도의 스레드에서 GStreamer 관련 작업을 수행하는 Qt 애플리케이션이 있습니다. 비록 내가 라고 생각하면 신호 콜백을 설정하는 규칙을 따라 왔지만, 지정한 콜백 함수는 호출되지 않는 것 같습니다.GStreamer가 콜백을 호출하지 않는 것 같습니다.

콜백 함수가 다음과

, 그것은 할 시도하는 모든 디버깅 콘솔에 뭔가를 기록 할 수 있습니다 :

static gboolean Cb(GstBus *bus, GstMessage *msg, gpointer data) 
{ 
    std::cout << "g_sig, bus = " << (void*)bus 
       << ", msg = "  << (void*)msg 
       << ", data = "  << (void*)data 
       << std::endl; 
    return TRUE; 
} 

내가 시작하고 스트림 (라이브 RTSP/H.264 피드를 모니터링하는 데 사용하고 순서 이다)의 IP 카메라 :

GstElement *playBin = gst_parse_launch("<gstreamer pipeline>"); 
GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(playBin)); 
gst_bus_add_signal_watch(bus); 
g_signal_connect(bus, "message::state-changed", (GCallback)Cb, NULL); 
gst_element_set_state(playBin, GST_STATE_PLAYING); 

GMainLoop *mainLoop = g_main_loop_new(NULL, FALSE); 
g_main_loop_run(mainLoop); 

이제 스트림 실제로 재생 (비디오가 나타납니다) 그래서 내가 거기에 아무 문제가 없습니다 겠지입니다. 그러나 파이프 라인이 재생되기 시작하면 상태 변경 메시지를 게시해야합니다. Cb()의 출력을 보지 못해서 이런 일이 일어나지 않는 것 같습니다.

또한 message::eos, message::errormessage::element 신호를 잡아도 출력이 없습니다.

위의 코드가 약간 문제가되는 것은 확실하지 않지만, 위의 코드가 약간 단순화되었습니다. 실제로 두 개의 스트림이 재생되므로 위 코드의 첫 번째 코드 단편이 각 playbin에 대해 두 번 발생합니다 (시퀀스는 각각 정확합니다. 코드를 불필요하게 복잡하게 만들 필요가 없습니다).

그러면 기본 루프가 만들어져 실행됩니다.

앞에서 설명한 것처럼 콜백 함수의 출력이 표시되지 않으므로 메시지가 어디로 이동합니까?

부록 : 가치가있는 부분에 대해서는 gst_bus_add_watch 메서드를 사용하여 특정 신호가 아닌 모두 메시지를 캡처하려고 시도했지만 아무 것도 나타나지 않습니다. 또한 Qt 애플리케이션이므로 코드에는 gtk_init이 없다는 것을 언급해야합니다. 간단히 말해서 메인 스레드에서 gst_init이라고 부릅니다.

+1

실제 코드에서 모든 호출 된 함수 (특히 g_signal_connect)의 반환 값을 확인한다고 가정합니다. – Silicomancer

+0

어떤 이유로 stdout이 리디렉션 될 수 있습니다. 'Cb()'함수에서 중단 점에 넣으려고 했습니까? – MrEricSir

답변

1

gstreamer에 대한 지식이 제한적이므로 오래 전부터 사용 해봤습니다.

나는 약간의 테스트를했고,이 작동하는 것 같다 :

메시지가 버스에 게시되어 있습니다

#include <stdio.h> 
#include <gstreamer-1.0/gst/gst.h> 

static gboolean Cb(GstBus *bus, GstMessage *msg, gpointer data) 
{ 
     printf("g_sig, bus = %x, msg = %s, data = %x\n", 
      bus, 
      gst_message_type_get_name(GST_MESSAGE_TYPE(msg)), 
      data); 

     return TRUE; 
} 

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://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL); 

     /* Wait until error or EOS */ 
     bus = gst_element_get_bus (pipeline); 

     /* use the sync signal handler to link elements while the pipeline is still 
     * doing the state change */ 
     gst_bus_set_sync_handler (bus, gst_bus_sync_signal_handler, pipeline, NULL); 
     g_object_connect (bus, "signal::sync-message::state-changed", G_CALLBACK (Cb), pipeline, NULL); 

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

     msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS); 

     /* Free resources */ 
     if (msg != NULL) 
       gst_message_unref (msg); 

     gst_object_unref (bus); 
     gst_element_set_state (pipeline, GST_STATE_NULL); 
     gst_object_unref (pipeline); 

     return 0; 
} 

그러나 message::state-changed있다. 이 신호는 메인 루프에 추가 된 GSource에서 방출됩니다. 이 신호는 메인 루프가 실행 중일 때만 방출됩니다. 대신

signal::sync-message::state-changed : 메시지가 버스에 게시되어 있습니다

. 이 신호는 메시지를 게시 한 스레드에서 방출되므로 잠금에주의해야합니다.

그래서 sync-message는 메인 루프 외부에서도 방출됩니다.

두 신호 모두에 대해 docs.

+0

이 답변으로 OP가 도움이되었는지 확신 할 수 없지만 다른 언급이 없으므로 귀하의 답변에 현상금을 수여하고 있습니다. 큰 노력에 감사드립니다. – user2728397

관련 문제