diff --git a/debian/control b/debian/control index e947035..d4e885f 100644 --- a/debian/control +++ b/debian/control @@ -8,5 +8,5 @@ Homepage: https://github.com/derekdai/miraclecast Package: miraclecast Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} +Depends: ${shlibs:Depends}, ${misc:Depends}, gstreamer1.0-tools, gstreamer1.0-vaapi Description: Connect external monitors to your system via Wifi-Display specification also known as Miracast diff --git a/src/ctl/wfd-out-session.c b/src/ctl/wfd-out-session.c index 69425f4..7000663 100644 --- a/src/ctl/wfd-out-session.c +++ b/src/ctl/wfd-out-session.c @@ -18,6 +18,8 @@ */ #define LOG_SUBSYSTEM "wfd-session" +#include +#include #include #include "wfd-session.h" #include "shl_log.h" @@ -171,6 +173,11 @@ static int wfd_out_session_initiate_io(struct wfd_session *s, static void wfd_out_session_end(struct wfd_session *s) { struct wfd_out_session *os = wfd_out_session(s); + + if(-1 != s->stream.gst) { + kill(s->stream.gst, SIGTERM); + } + if(0 <= os->fd) { close(os->fd); os->fd = -1; @@ -399,6 +406,80 @@ static int wfd_out_session_request_options(struct wfd_session *s, return 0; } +static int wfd_out_session_launch_gst(struct wfd_session *s, pid_t *out) +{ + sigset_t sigset; + char port[10]; + char * args[] = { + "gst-launch-1.0", + "-v", + "ximagesrc", + "use-damage=false", + "show-pointer=false", + "startx=0", + "starty=0", + "endx=1279", + "endy=719", + "!", "vaapipostproc", + "!", "video/x-raw,", + "format=YV12", + "!", "vaapih264enc", + /*"!", "video/x-h264,",*/ + /*"stream-format=byte-steram,",*/ + /*"profile=high",*/ + /*"!", "queue",*/ + "!", "mpegtsmux", + "!", "rtpmp2tpay", + "!", "udpsink", + "host=", wfd_out_session_get_sink(s)->peer->remote_address, + "port=", port, + NULL + }; + + snprintf(port, sizeof(port), "%hu", s->stream.rtp_port); + + pid_t p = fork(); + if(0 > p) { + return p; + } + else if(0 < p) { + *out = p; + return 0; + } + + sigemptyset(&sigset); + sigaddset(&sigset, SIGTERM); + sigprocmask(SIG_UNBLOCK, &sigset, NULL); + + execvpe(args[0], + args, + (char *[]) { + "XDG_RUNTIME_DIR=/run/user/1000", + "GST_DEBUG=3", + "DISPLAY=:0", + "XAUTHORITY=/run/user/1000/gdm/Xauthority", + NULL + }); + + exit(1); +} + +static int wfd_out_sessoin_handle_gst_term(sd_event_source *source, + const siginfo_t *si, + void *userdata) +{ + struct wfd_session *s = userdata; + + log_trace("gst-launch(%d) terminated", si->si_pid); + + if(WFD_SESSION_STATE_TEARING_DOWN != wfd_session_get_state(s)) { + s->stream.gst = -1; + wfd_session_end(s); + } + + return 0; +} + static int wfd_out_session_handle_play_request(struct wfd_session *s, struct rtsp_message *req, struct rtsp_message **out_rep, @@ -407,7 +488,8 @@ static int wfd_out_session_handle_play_request(struct wfd_session *s, { _shl_free_ char *v; _rtsp_message_unref_ struct rtsp_message *m = NULL; - int r; + pid_t gst; + int r, status; r = rtsp_message_new_reply_for(req, &m, @@ -432,6 +514,24 @@ static int wfd_out_session_handle_play_request(struct wfd_session *s, return r; } + r = wfd_out_session_launch_gst(s, &gst); + if(0 > r) { + return r; + } + + r = sd_event_add_child(ctl_wfd_get_loop(), + NULL, + gst, WEXITED, + wfd_out_sessoin_handle_gst_term, + s); + if(0 > r) { + kill(gst, SIGKILL); + waitpid(gst, &status, WNOHANG); + return r; + } + + s->stream.gst = gst; + *out_rep = m; m = NULL; @@ -572,8 +672,8 @@ static int wfd_out_session_request_set_parameter(struct wfd_session *s, s->stream.id = WFD_STREAM_ID_PRIMARY; r = asprintf(&body, - "wfd_video_formats: 38 00 02 10 00000080 00000000 00000000 00 0000 0000 11 none none\n" - "wfd_audio_codecs: AAC 00000001 00\n" + "wfd_video_formats: 00 00 02 10 00001401 00000000 00000000 00 0000 0000 00 none none\n" + //"wfd_audio_codecs: AAC 00000001 00\n" "wfd_presentation_URL: %s none\n" "wfd_client_rtp_ports: %u %u mode=play", //"wfd_uibc_capability: input_category_list=GENERIC\n;generic_cap_list=SingleTouch;hidc_cap_list=none;port=5100\n" diff --git a/src/ctl/wfd-session.c b/src/ctl/wfd-session.c index bad845e..b0a956e 100644 --- a/src/ctl/wfd-session.c +++ b/src/ctl/wfd-session.c @@ -124,6 +124,8 @@ void wfd_session_end(struct wfd_session *s) log_info("session %lu ended", s->id); + wfd_session_set_state(s, WFD_SESSION_STATE_TEARING_DOWN); + (*session_vtables[s->dir].end)(s); if(s->rtsp) { @@ -131,18 +133,24 @@ void wfd_session_end(struct wfd_session *s) s->rtsp = NULL; } - wfd_video_formats_free(s->vformats); - s->vformats = NULL; - wfd_audio_codecs_free(s->acodecs); - s->acodecs = NULL; + if(s->vformats) { + wfd_video_formats_free(s->vformats); + s->vformats = NULL; + } - free(s->stream.url); - s->stream.url = NULL; + if(s->acodecs) { + wfd_audio_codecs_free(s->acodecs); + s->acodecs = NULL; + } + + if(s->stream.url) { + free(s->stream.url); + s->stream.url = NULL; + } - s->last_request = RTSP_M_UNKNOWN; - wfd_session_set_state(s, WFD_SESSION_STATE_NULL); s->rtp_ports[0] = 0; s->rtp_ports[1] = 0; + s->last_request = RTSP_M_UNKNOWN; if(wfd_is_out_session(s)) { wfd_fn_out_session_ended(s); diff --git a/src/ctl/wfd-session.h b/src/ctl/wfd-session.h index 8834564..c2e8868 100644 --- a/src/ctl/wfd-session.h +++ b/src/ctl/wfd-session.h @@ -19,6 +19,7 @@ #ifndef MIRACLE_OUT_SESSION_H #define MIRACLE_OUT_SESSION_H +#include #include "ctl.h" #define wfd_out_session(s) (assert(wfd_is_out_session(s)), (struct wfd_out_session *) (s)) @@ -99,11 +100,13 @@ struct wfd_session enum wfd_stream_id id; char *url; uint16_t rtp_port; + pid_t gst; } stream; bool destructed: 1; }; +int wfd_session_init(struct wfd_session *s); const char * rtsp_message_id_to_string(enum rtsp_message_id id); struct wfd_sink * wfd_out_session_get_sink(struct wfd_session *s); int wfd_session_request(struct wfd_session *s, enum rtsp_message_id id);