diff --git a/CMakeLists.txt b/CMakeLists.txt index 690038f..ca46445 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ find_package(PkgConfig) pkg_check_modules (GLIB2 REQUIRED glib-2.0) pkg_check_modules (UDEV REQUIRED libudev) pkg_check_modules (SYSTEMD REQUIRED libsystemd) +pkg_check_modules (GSTREAMER REQUIRED gstreamer-1.0) include(CheckCCompilerFlag) check_c_compiler_flag(-fstack-protector-strong HAS_STACK_PROTCTOR_STRONG) diff --git a/src/ctl/CMakeLists.txt b/src/ctl/CMakeLists.txt index aae4b05..ec9c389 100644 --- a/src/ctl/CMakeLists.txt +++ b/src/ctl/CMakeLists.txt @@ -57,7 +57,7 @@ set(miracle-wfdctl_SRCS ctl-cli.c wfd-arg.c) include_directories(${CMAKE_BINARY_DIR} - ${GLIB2_INCLUDE_DIRS} + ${GSTREAMER_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/shared) @@ -73,7 +73,9 @@ if(READLINE_FOUND) target_link_libraries(miracle-wfdctl ${READLINE_LIBRARY}) endif(READLINE_FOUND) -target_link_libraries(miracle-wfdctl miracle-shared ${GLIB2_LIBRARIES}) +target_link_libraries(miracle-wfdctl + miracle-shared + ${GSTREAMER_LIBRARIES}) ########### install files ############### diff --git a/src/ctl/wfd-out-session.c b/src/ctl/wfd-out-session.c index e483b44..ed96637 100644 --- a/src/ctl/wfd-out-session.c +++ b/src/ctl/wfd-out-session.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "wfd-session.h" #include "shl_log.h" #include "rtsp.h" @@ -49,6 +50,8 @@ struct wfd_out_session uint16_t height; enum wfd_resolution_standard std; uint32_t mask; + + GstElement *pipeline; }; static const struct rtsp_dispatch_entry out_session_rtsp_disp_tbl[]; @@ -227,20 +230,6 @@ int wfd_out_session_initiate_io(struct wfd_session *s, return 0; } -static void wfd_out_session_kill_gst(struct wfd_session *s) -{ - pid_t pid; - struct wfd_out_session *os = wfd_out_session(s); - - if(os->gst_term_source) { - sd_event_source_get_child_pid(os->gst_term_source, &pid); - kill(pid, SIGTERM); - - sd_event_source_set_userdata(os->gst_term_source, NULL); - os->gst_term_source = NULL; - } -} - int wfd_out_session_resume(struct wfd_session *s) { return wfd_session_request(s, @@ -280,7 +269,11 @@ void wfd_out_session_destroy(struct wfd_session *s) os->display_name = NULL; } - wfd_out_session_kill_gst(s); + if(os->pipeline) { + gst_element_set_state(os->pipeline, GST_STATE_NULL); + g_object_unref(os->pipeline); + os->pipeline = NULL; + } } int wfd_out_session_initiate_request(struct wfd_session *s) @@ -501,13 +494,14 @@ inline static char * uint16_to_str(uint16_t i, char *buf, size_t len) return buf; } -static int wfd_out_session_launch_gst(struct wfd_session *s, pid_t *out) +static int wfd_out_session_create_pipeline(struct wfd_session *s) { - sigset_t sigset; char x[16], y[16], width[16], height[16], port[16]; struct wfd_out_session *os = wfd_out_session(s); - char * args[] = { - "gst-launch-1.0", + GstElement *pipeline; + GError *error = NULL; + GstStateChangeReturn r; + const char * pipeline_desc[] = { "ximagesrc", "use-damage=false", "show-pointer=false", @@ -519,10 +513,6 @@ static int wfd_out_session_launch_gst(struct wfd_session *s, pid_t *out) "!", "video/x-raw,", "format=YV12", "!", "vaapih264enc", - /*"!", "video/x-h264,",*/ - /*"stream-format=byte-steram,",*/ - /*"profile=high",*/ - /*"!", "queue",*/ "!", "mpegtsmux", "!", "rtpmp2tpay", "!", "udpsink", @@ -531,47 +521,22 @@ static int wfd_out_session_launch_gst(struct wfd_session *s, pid_t *out) NULL }; - pid_t p = fork(); - if(0 > p) { - return p; - } - else if(0 < p) { - log_info("gstreamer (%d) is launched for session %u", - p, - s->id); - - *out = p; - return 0; + pipeline = gst_parse_launchv(pipeline_desc, &error); + if(!pipeline) { + if(error) { + log_error("failed to create pipeline: %s", error->message); + g_error_free(error); + } + return -1; } - sigemptyset(&sigset); - sigaddset(&sigset, SIGTERM); - sigprocmask(SIG_UNBLOCK, &sigset, NULL); - - execvp(args[0], args); - - exit(1); -} - -static int wfd_out_session_handle_gst_term(sd_event_source *source, - const siginfo_t *si, - void *userdata) -{ - struct wfd_out_session *os = userdata; - - log_trace("gst-launch(%d) terminated", si->si_pid); - - sd_event_source_unref(source); - - if(!os) { - return 0; + r = gst_element_set_state(pipeline, GST_STATE_READY); + if(GST_STATE_CHANGE_FAILURE == r) { + g_object_unref(pipeline); + return -1; } - os->gst_term_source = NULL; - - if(WFD_SESSION_STATE_PAUSED != wfd_session(os)->state) { - wfd_session_teardown(wfd_session(os)); - } + os->pipeline = pipeline; return 0; } @@ -583,7 +548,7 @@ static int wfd_out_session_handle_pause_request(struct wfd_session *s, _rtsp_message_unref_ struct rtsp_message *m = NULL; int r; - wfd_out_session_kill_gst(s); + gst_element_set_state(wfd_out_session(s)->pipeline, GST_STATE_READY); r = rtsp_message_new_reply_for(req, &m, @@ -606,7 +571,7 @@ static int wfd_out_session_handle_teardown_request(struct wfd_session *s, _rtsp_message_unref_ struct rtsp_message *m = NULL; int r; - wfd_out_session_kill_gst(s); + gst_element_set_state(wfd_out_session(s)->pipeline, GST_STATE_NULL); r = rtsp_message_new_reply_for(req, &m, @@ -627,33 +592,19 @@ static int wfd_out_session_post_handle_play(sd_event_source *source, void *userdata) { struct wfd_session *s = userdata; - int r, status; - pid_t gst; + GstStateChangeReturn r; sd_event_source_unref(source); wfd_out_session(s)->gst_launch_source = NULL; - if(getenv("DO_NOT_LAUNCH_GST")) { - return 0; - } - - r = wfd_out_session_launch_gst(s, &gst); - if(0 > r) { - return r; - } - - r = sd_event_add_child(ctl_wfd_get_loop(), - &wfd_out_session(s)->gst_term_source, - gst, WEXITED, - wfd_out_session_handle_gst_term, - s); - if(0 > r) { - kill(gst, SIGKILL); - waitpid(gst, &status, WNOHANG); + r = gst_element_set_state(wfd_out_session(s)->pipeline, + GST_STATE_PLAYING); + if(GST_STATE_CHANGE_FAILURE == r) { wfd_session_teardown(s); + return -1; } - return r; + return 0; } static int wfd_out_session_handle_play_request(struct wfd_session *s, @@ -763,6 +714,11 @@ static int wfd_out_session_handle_setup_request(struct wfd_session *s, return r; } + r = wfd_out_session_create_pipeline(s); + if(0 > r) { + return r; + } + *out_rep = m; m = NULL; diff --git a/src/ctl/wfdctl.c b/src/ctl/wfdctl.c index d5ddda4..f16246a 100644 --- a/src/ctl/wfdctl.c +++ b/src/ctl/wfdctl.c @@ -510,10 +510,12 @@ int main(int argc, char **argv) log_max_sev = log_parse_arg(getenv("LOG_LEVEL")); } + gst_init(&argc, &argv); + loop = g_main_loop_new(NULL, FALSE); if(!loop) { r = -ENOMEM; - goto end; + goto deinit_gst; } r = sd_event_default(&event); @@ -581,7 +583,8 @@ unref_event: sd_event_unref(event); unref_loop: g_main_loop_unref(loop); -end: +deinit_gst: + gst_deinit(); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; }