1 /*
2  * This file is part of Wireless Display Software for Linux OS
3  *
4  * Copyright (C) 2014 Intel Corporation.
5  *
6  * Contact: Alexander Kanavin <alex.kanavin@gmail.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  */
23 
24 #include <iostream>
25 #include <gio/gio.h>
26 
27 #include "mirac-gst-test-source.hpp"
28 #include "mirac-gst-bus-handler.hpp"
29 #include "libwds/public/logging.h"
30 
MiracGstTestSource(wfd_test_stream_t wfd_stream_type,std::string hostname,int port)31 MiracGstTestSource::MiracGstTestSource (wfd_test_stream_t wfd_stream_type, std::string hostname, int port)
32 {
33     std::string gst_pipeline;
34 
35     std::string hostname_port = (!hostname.empty() ? "host=" + hostname + " ": " ") + (port > 0 ? "port=" + std::to_string(port) : "");
36 
37     if (wfd_stream_type == WFD_TEST_BOTH) {
38         gst_pipeline = "videotestsrc ! videoconvert ! video/x-raw,format=I420 ! x264enc ! muxer.  audiotestsrc ! avenc_ac3 ! muxer.  mpegtsmux name=muxer ! rtpmp2tpay ! udpsink name=sink " +
39             hostname_port;
40     } else if (wfd_stream_type == WFD_TEST_AUDIO) {
41         gst_pipeline = "audiotestsrc ! avenc_ac3 ! mpegtsmux ! rtpmp2tpay ! udpsink name=sink " + hostname_port;
42     } else if (wfd_stream_type == WFD_TEST_VIDEO) {
43         gst_pipeline = "videotestsrc ! videoconvert ! video/x-raw,format=I420 ! x264enc ! mpegtsmux ! rtpmp2tpay ! udpsink name=sink " + hostname_port;
44     } else if (wfd_stream_type == WFD_DESKTOP) {
45         gst_pipeline = "ximagesrc ! videoconvert ! video/x-raw,format=I420 ! x264enc tune=zerolatency ! mpegtsmux ! rtpmp2tpay ! udpsink name=sink " + hostname_port;
46     }
47 
48     GError *err = NULL;
49     gst_elem = gst_parse_launch(gst_pipeline.c_str(), &err);
50     if (err != NULL) {
51         WDS_ERROR("Cannot initialize gstreamer pipeline: [%s] %s", g_quark_to_string(err->domain), err->message);
52     }
53 
54     if (gst_elem) {
55         GstBus* bus = gst_pipeline_get_bus (GST_PIPELINE (gst_elem));
56         bus_watch_id = gst_bus_add_watch (bus, mirac_gstbus_callback, this);
57         gst_object_unref (bus);
58     }
59 }
60 
SetState(GstState state)61 void MiracGstTestSource::SetState(GstState state)
62 {
63     if (gst_elem) {
64         gst_element_set_state (gst_elem, state);
65     }
66 }
67 
GetState() const68 GstState MiracGstTestSource::GetState() const
69 {
70     if (!gst_elem)
71         return GST_STATE_NULL;
72     GstState result;
73     gst_element_get_state (gst_elem, &result, NULL, GST_CLOCK_TIME_NONE);
74     return result;
75 }
76 
UdpSourcePort()77 int MiracGstTestSource::UdpSourcePort()
78 {
79     if (gst_elem == NULL)
80         return 0;
81 
82     GstElement* sink = NULL;
83     sink = gst_bin_get_by_name(GST_BIN(gst_elem), "sink");
84 
85     if (sink == NULL)
86         return 0;
87 
88     GSocket* socket = NULL;
89     g_object_get(sink, "used-socket", &socket, NULL);
90     if (socket == NULL)
91         return 0;
92 
93     guint16 port = g_inet_socket_address_get_port(G_INET_SOCKET_ADDRESS(g_socket_get_local_address(socket, NULL)));
94 
95     return port;
96 }
97 
~MiracGstTestSource()98 MiracGstTestSource::~MiracGstTestSource ()
99 {
100     if (gst_elem) {
101         gst_element_set_state (gst_elem, GST_STATE_NULL);
102         g_source_remove (bus_watch_id);
103         gst_object_unref (GST_OBJECT (gst_elem));
104     }
105 }
106