mirror of
https://github.com/albfan/miraclecast.git
synced 2025-02-15 04:42:06 +00:00
miracle-dispd: stablizing and removing memory leak
This commit is contained in:
parent
aa5d6c0468
commit
e117704d4e
9 changed files with 438 additions and 453 deletions
|
@ -41,6 +41,7 @@ errordomain WfdCtlError
|
||||||
TIMEOUT,
|
TIMEOUT,
|
||||||
MONITOR_GONE,
|
MONITOR_GONE,
|
||||||
FORMATION_ERROR,
|
FORMATION_ERROR,
|
||||||
|
NO_P2P_SUPPORT,
|
||||||
}
|
}
|
||||||
|
|
||||||
private void print(string format, ...)
|
private void print(string format, ...)
|
||||||
|
@ -335,17 +336,20 @@ private class WfdCtl : GLib.Application
|
||||||
opt_iface);
|
opt_iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!l.managed) {
|
if(l.managed) {
|
||||||
info("wifid is acquiring ownership of %s...", opt_iface);
|
info("wifid is releasing ownership of %s...", opt_iface);
|
||||||
|
l.unmanage();
|
||||||
l.manage();
|
|
||||||
yield wait_prop_changed(l, "Managed");
|
yield wait_prop_changed(l, "Managed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info("wifid is acquiring ownership of %s...", opt_iface);
|
||||||
|
l.manage();
|
||||||
|
yield wait_prop_changed(l, "Managed");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void start_p2p_scan() throws Error
|
private async void start_p2p_scan() throws Error
|
||||||
{
|
{
|
||||||
Link l = find_link_by_name(opt_iface);
|
Link? l = find_link_by_name(opt_iface);
|
||||||
if(l.wfd_subelements != opt_wfd_subelems) {
|
if(l.wfd_subelements != opt_wfd_subelems) {
|
||||||
info("update wfd_subelems to broadcast what kind of device we are");
|
info("update wfd_subelems to broadcast what kind of device we are");
|
||||||
|
|
||||||
|
@ -354,7 +358,7 @@ private class WfdCtl : GLib.Application
|
||||||
}
|
}
|
||||||
|
|
||||||
if(-1 == l.p2p_state) {
|
if(-1 == l.p2p_state) {
|
||||||
error("link %s has no P2P supporting", l.interface_name);
|
throw new WfdCtlError.NO_P2P_SUPPORT("link %s has no P2P supporting", l.interface_name);
|
||||||
}
|
}
|
||||||
else if(0 == l.p2p_state) {
|
else if(0 == l.p2p_state) {
|
||||||
info("wait for P2P supporting status...");
|
info("wait for P2P supporting status...");
|
||||||
|
@ -568,24 +572,23 @@ private class WfdCtl : GLib.Application
|
||||||
yield form_p2p_group();
|
yield form_p2p_group();
|
||||||
yield establish_session();
|
yield establish_session();
|
||||||
yield wait_for_session_ending();
|
yield wait_for_session_ending();
|
||||||
yield release_wnic_ownership();
|
|
||||||
|
|
||||||
quit();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop_wireless_display()
|
public void stop_wireless_display()
|
||||||
{
|
{
|
||||||
info("tearing down wireless display...");
|
|
||||||
|
|
||||||
if(null != curr_session) {
|
if(null != curr_session) {
|
||||||
|
info("tearing down wireless display...");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
curr_session.teardown();
|
curr_session.teardown();
|
||||||
}
|
}
|
||||||
catch(Error e) {
|
catch(Error e) {
|
||||||
warning("failed to tearing down normally: %s", e.message);
|
warning("failed to tearing down normally: %s", e.message);
|
||||||
quit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wait_prop_changed.begin(curr_sink, "Session", 3, () => {
|
||||||
|
release_wnic_ownership.begin(quit);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
release_wnic_ownership.begin(quit);
|
release_wnic_ownership.begin(quit);
|
||||||
|
@ -598,44 +601,27 @@ private class WfdCtl : GLib.Application
|
||||||
print("please specify a peer MAC with -p option");
|
print("please specify a peer MAC with -p option");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
print("peer-mac=%s", opt_peer_mac);
|
||||||
|
|
||||||
if(null == opt_display) {
|
if(null == opt_display) {
|
||||||
opt_display = Environment.get_variable("DISPLAY");
|
opt_display = Environment.get_variable("DISPLAY");
|
||||||
if(null == opt_display) {
|
|
||||||
print("no video source found. play specify one by DISPLAY " +
|
|
||||||
"environment or -d option");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print("no display name specified by -d, " +
|
|
||||||
"use DISPLAY environment variable instead");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
print("display=%s", opt_display);
|
||||||
|
|
||||||
if(null == opt_authority) {
|
if(null == opt_authority) {
|
||||||
opt_authority = Environment.get_variable("XAUTHORITY");
|
opt_authority = Environment.get_variable("XAUTHORITY");
|
||||||
if(null == opt_authority) {
|
|
||||||
print("no display authority found. play specify one by XAUTHORITY " +
|
|
||||||
"environment or -x option");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print("no display authority specified by -x, " +
|
|
||||||
"use XAUTHORITY environment variable instead");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
print("authority=%s", opt_authority);
|
||||||
|
|
||||||
if(null == opt_iface) {
|
if(null == opt_iface) {
|
||||||
opt_iface = "wlan0";
|
opt_iface = "wlan0";
|
||||||
print("no wireless adapter specified by -i, use '%s' instead",
|
|
||||||
opt_iface);
|
|
||||||
}
|
}
|
||||||
|
print("interface=%s", opt_iface);
|
||||||
|
|
||||||
if(null == opt_wfd_subelems) {
|
if(null == opt_wfd_subelems) {
|
||||||
opt_wfd_subelems = "000600111c4400c8";
|
opt_wfd_subelems = "000600111c4400c8";
|
||||||
print("no wfd_subelems specified by -w, use '%s' instead",
|
|
||||||
opt_wfd_subelems);
|
|
||||||
}
|
}
|
||||||
|
print("wfd_subelemens=%s", opt_wfd_subelems);
|
||||||
|
|
||||||
display = Gdk.Display.open(opt_display);
|
display = Gdk.Display.open(opt_display);
|
||||||
if(null == display) {
|
if(null == display) {
|
||||||
|
@ -653,6 +639,7 @@ private class WfdCtl : GLib.Application
|
||||||
print("invalid screen number option: %d", opt_monitor_num);
|
print("invalid screen number option: %d", opt_monitor_num);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
print("monitor-num=%d", opt_monitor_num);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -671,6 +658,16 @@ private class WfdCtl : GLib.Application
|
||||||
print("failed to cast to wireless display: %s", e.message);
|
print("failed to cast to wireless display: %s", e.message);
|
||||||
release();
|
release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
release_wnic_ownership.begin((o, r) => {
|
||||||
|
try {
|
||||||
|
release_wnic_ownership.end(r);
|
||||||
|
}
|
||||||
|
catch(Error e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
quit();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
hold();
|
hold();
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#define wfd_session_has_id(s) (0 < wfd_session_get_id(s))
|
#define wfd_session_has_id(s) (0 < wfd_session_get_id(s))
|
||||||
#define wfd_is_out_session(s) (WFD_SESSION_DIR_OUT == wfd_session_get_dir(s))
|
#define wfd_is_out_session(s) (WFD_SESSION_DIR_OUT == wfd_session_get_dir(s))
|
||||||
#define wfd_is_in_session(s) (WFD_SESSION_DIR_IN == wfd_session_get_dir(s))
|
#define wfd_is_in_session(s) (WFD_SESSION_DIR_IN == wfd_session_get_dir(s))
|
||||||
#define _wfd_session_free_ _shl_cleanup_(wfd_session_free_p)
|
#define _wfd_session_unref_ _shl_cleanup_(wfd_session_unrefp)
|
||||||
|
|
||||||
struct wfd_sink;
|
struct wfd_sink;
|
||||||
struct wfd_session;
|
struct wfd_session;
|
||||||
|
@ -76,10 +76,11 @@ int wfd_session_is_established(struct wfd_session *s);
|
||||||
int wfd_session_resume(struct wfd_session *s);
|
int wfd_session_resume(struct wfd_session *s);
|
||||||
int wfd_session_pause(struct wfd_session *s);
|
int wfd_session_pause(struct wfd_session *s);
|
||||||
int wfd_session_teardown(struct wfd_session *s);
|
int wfd_session_teardown(struct wfd_session *s);
|
||||||
void wfd_session_free(struct wfd_session *s);
|
struct wfd_session * wfd_session_ref(struct wfd_session *s);
|
||||||
|
void wfd_session_unref(struct wfd_session *s);
|
||||||
uint64_t wfd_session_get_id(struct wfd_session *s);
|
uint64_t wfd_session_get_id(struct wfd_session *s);
|
||||||
struct wfd_sink * wfd_out_session_get_sink(struct wfd_session *s);
|
struct wfd_sink * wfd_out_session_get_sink(struct wfd_session *s);
|
||||||
void wfd_session_free_p(struct wfd_session **s);
|
void wfd_session_unrefp(struct wfd_session **s);
|
||||||
unsigned int * wfd_session_to_htable(struct wfd_session *s);
|
unsigned int * wfd_session_to_htable(struct wfd_session *s);
|
||||||
struct wfd_session * wfd_session_from_htable(unsigned int *e);
|
struct wfd_session * wfd_session_from_htable(unsigned int *e);
|
||||||
|
|
||||||
|
|
166
src/disp/dispd.c
166
src/disp/dispd.c
|
@ -25,8 +25,6 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <systemd/sd-event.h>
|
#include <systemd/sd-event.h>
|
||||||
#include <systemd/sd-daemon.h>
|
#include <systemd/sd-daemon.h>
|
||||||
#include <glib.h>
|
|
||||||
#include <gst/gst.h>
|
|
||||||
#include "ctl.h"
|
#include "ctl.h"
|
||||||
#include "disp.h"
|
#include "disp.h"
|
||||||
#include "wfd.h"
|
#include "wfd.h"
|
||||||
|
@ -103,6 +101,43 @@ static void ctl_wfd_free(struct ctl_wfd *wfd)
|
||||||
free(wfd);
|
free(wfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ctl_wfd_handle_shutdown(sd_event_source *s,
|
||||||
|
uint64_t usec,
|
||||||
|
void *userdata)
|
||||||
|
{
|
||||||
|
struct ctl_wfd *wfd = userdata;
|
||||||
|
|
||||||
|
sd_event_source_set_enabled(s, false);
|
||||||
|
sd_event_source_unref(s);
|
||||||
|
|
||||||
|
sd_event_exit(wfd->loop, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ctl_wfd_shutdown(struct ctl_wfd *wfd)
|
||||||
|
{
|
||||||
|
uint64_t now;
|
||||||
|
int r = sd_event_now(ctl_wfd_get_loop(), CLOCK_MONOTONIC, &now);
|
||||||
|
if(0 > r) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_event_add_time(ctl_wfd_get_loop(),
|
||||||
|
NULL,
|
||||||
|
CLOCK_MONOTONIC,
|
||||||
|
now + 100 * 1000,
|
||||||
|
0,
|
||||||
|
ctl_wfd_handle_shutdown,
|
||||||
|
wfd);
|
||||||
|
if(0 <= r) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
sd_event_exit(wfd->loop, 0);
|
||||||
|
}
|
||||||
|
|
||||||
int ctl_wfd_add_sink(struct ctl_wfd *wfd,
|
int ctl_wfd_add_sink(struct ctl_wfd *wfd,
|
||||||
struct ctl_peer *p,
|
struct ctl_peer *p,
|
||||||
union wfd_sube *sube,
|
union wfd_sube *sube,
|
||||||
|
@ -407,90 +442,9 @@ void cli_fn_help()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* see: https://lists.freedesktop.org/archives/systemd-devel/2014-August/022329.html
|
|
||||||
**/
|
|
||||||
#define SD_SOURCE(p) ((SDSource *) (p))
|
|
||||||
|
|
||||||
typedef struct _SDSource SDSource;
|
|
||||||
|
|
||||||
struct _SDSource
|
|
||||||
{
|
|
||||||
GSource source;
|
|
||||||
sd_event *event;
|
|
||||||
GPollFD pollfd;
|
|
||||||
};
|
|
||||||
|
|
||||||
static gboolean sd_source_prepare(GSource *source, gint *timeout)
|
|
||||||
{
|
|
||||||
return sd_event_prepare(SD_SOURCE(source)->event) > 0 ? TRUE : FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean sd_source_check(GSource *source)
|
|
||||||
{
|
|
||||||
return sd_event_wait(SD_SOURCE(source)->event, 0) > 0 ? TRUE : FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean sd_source_dispatch(GSource *source,
|
|
||||||
GSourceFunc callback,
|
|
||||||
gpointer userdata)
|
|
||||||
{
|
|
||||||
return sd_event_dispatch(SD_SOURCE(source)->event) >= 0
|
|
||||||
? G_SOURCE_CONTINUE
|
|
||||||
: G_SOURCE_REMOVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sd_source_finalize(GSource *source)
|
|
||||||
{
|
|
||||||
sd_event_unref(SD_SOURCE(source)->event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sd_source_on_exit(sd_event_source *source, void *userdata)
|
|
||||||
{
|
|
||||||
g_main_loop_quit(userdata);
|
|
||||||
|
|
||||||
sd_event_source_set_enabled(source, false);
|
|
||||||
sd_event_source_unref(source);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sd_source_attach(GSource *source, GMainLoop *loop)
|
|
||||||
{
|
|
||||||
g_source_set_name(source, "sd-event");
|
|
||||||
g_source_add_poll(source, &SD_SOURCE(source)->pollfd);
|
|
||||||
g_source_attach(source, g_main_loop_get_context(loop));
|
|
||||||
|
|
||||||
return sd_event_add_exit(SD_SOURCE(source)->event,
|
|
||||||
NULL,
|
|
||||||
sd_source_on_exit,
|
|
||||||
loop);
|
|
||||||
}
|
|
||||||
|
|
||||||
GSource * sd_source_new(sd_event *event)
|
|
||||||
{
|
|
||||||
static GSourceFuncs funcs = {
|
|
||||||
sd_source_prepare,
|
|
||||||
sd_source_check,
|
|
||||||
sd_source_dispatch,
|
|
||||||
sd_source_finalize,
|
|
||||||
};
|
|
||||||
GSource *s = g_source_new(&funcs, sizeof(SDSource));
|
|
||||||
if(s) {
|
|
||||||
SD_SOURCE(s)->event = sd_event_ref(event);
|
|
||||||
SD_SOURCE(s)->pollfd.fd = sd_event_get_fd(event);
|
|
||||||
SD_SOURCE(s)->pollfd.events = G_IO_IN | G_IO_HUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
GMainLoop *loop;
|
|
||||||
GSource *source;
|
|
||||||
sd_event *event;
|
sd_event *event;
|
||||||
sd_bus *bus;
|
sd_bus *bus;
|
||||||
|
|
||||||
|
@ -501,17 +455,10 @@ int main(int argc, char **argv)
|
||||||
log_max_sev = log_parse_arg(getenv("LOG_LEVEL"));
|
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 deinit_gst;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_event_default(&event);
|
r = sd_event_default(&event);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
goto unref_loop;
|
log_warning("can't create default event loop");
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_event_set_watchdog(event, true);
|
r = sd_event_set_watchdog(event, true);
|
||||||
|
@ -520,33 +467,20 @@ int main(int argc, char **argv)
|
||||||
goto unref_event;
|
goto unref_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
source = sd_source_new(event);
|
|
||||||
if(!source) {
|
|
||||||
r = -ENOMEM;
|
|
||||||
goto unref_event;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_source_attach(source, loop);
|
|
||||||
if(0 > r) {
|
|
||||||
goto unref_source;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_bus_default_system(&bus);
|
r = sd_bus_default_system(&bus);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
log_warning("unable to connect to system DBus: %s", strerror(errno));
|
log_warning("unable to connect to system DBus: %s", strerror(errno));
|
||||||
goto unref_source;
|
goto disable_watchdog;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_bus_attach_event(bus, event, 0);
|
r = sd_bus_attach_event(bus, event, 0);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
log_warning("unable to attache DBus event source to loop: %s",
|
|
||||||
strerror(errno));
|
|
||||||
goto unref_bus;
|
goto unref_bus;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = ctl_wfd_new(&wfd, event, bus);
|
r = ctl_wfd_new(&wfd, event, bus);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
goto bus_detach_event;;
|
goto bus_detach_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = wfd_dbus_new(&wfd_dbus, event, bus);
|
r = wfd_dbus_new(&wfd_dbus, event, bus);
|
||||||
|
@ -567,31 +501,23 @@ int main(int argc, char **argv)
|
||||||
goto free_wfd_dbus;
|
goto free_wfd_dbus;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_main_loop_run(loop);
|
sd_event_loop(event);
|
||||||
|
|
||||||
sd_notify(false, "STATUS=Exiting..");
|
sd_notify(false, "STATUS=Exiting..");
|
||||||
|
|
||||||
free_wfd_dbus:
|
free_wfd_dbus:
|
||||||
wfd_dbus_free(wfd_dbus);
|
wfd_dbus_free(wfd_dbus);
|
||||||
wfd_dbus = NULL;
|
|
||||||
free_ctl_wfd:
|
free_ctl_wfd:
|
||||||
ctl_wfd_free(wfd);
|
ctl_wfd_free(wfd);
|
||||||
wfd = NULL;
|
|
||||||
bus_detach_event:
|
bus_detach_event:
|
||||||
sd_bus_detach_event(bus);
|
sd_bus_detach_event(bus);
|
||||||
unref_bus:
|
unref_bus:
|
||||||
sd_bus_flush_close_unref(bus);
|
sd_bus_flush_close_unref(bus);
|
||||||
unref_source:
|
disable_watchdog:
|
||||||
g_source_ref(source);
|
|
||||||
g_source_destroy(source);
|
|
||||||
unref_event:
|
|
||||||
sd_event_run(event, 0);
|
|
||||||
sd_event_unref(event);
|
|
||||||
unref_loop:
|
|
||||||
g_main_loop_unref(loop);
|
|
||||||
deinit_gst:
|
|
||||||
gst_deinit();
|
|
||||||
sd_event_set_watchdog(event, false);
|
sd_event_set_watchdog(event, false);
|
||||||
|
unref_event:
|
||||||
|
sd_event_unref(event);
|
||||||
|
end:
|
||||||
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
gstreamer = dependency('gstreamer-1.0')
|
|
||||||
gstreamer_base = dependency('gstreamer-base-1.0')
|
|
||||||
|
|
||||||
inc = include_directories('../..', '../ctl',)
|
inc = include_directories('../..', '../ctl',)
|
||||||
deps = [libsystemd, gstreamer, gstreamer_base, libmiracle_shared_dep]
|
deps = [libsystemd, libmiracle_shared_dep]
|
||||||
if readline.found()
|
if readline.found()
|
||||||
deps += [readline]
|
deps += [readline]
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <systemd/sd-bus.h>
|
#include <systemd/sd-bus.h>
|
||||||
#include "disp.h"
|
#include "disp.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "shl_log.h"
|
||||||
#include "wfd-dbus.h"
|
#include "wfd-dbus.h"
|
||||||
|
|
||||||
#define wfd_dbus_object_added(o, argv...) ({ \
|
#define wfd_dbus_object_added(o, argv...) ({ \
|
||||||
|
@ -370,7 +371,7 @@ static int wfd_dbus_sink_start_session(sd_bus_message *m,
|
||||||
sd_bus_error *ret_error)
|
sd_bus_error *ret_error)
|
||||||
{
|
{
|
||||||
struct wfd_sink *sink = userdata;
|
struct wfd_sink *sink = userdata;
|
||||||
_wfd_session_free_ struct wfd_session *session = NULL;
|
_wfd_session_unref_ struct wfd_session *session = NULL;
|
||||||
_shl_free_ char *path = NULL;
|
_shl_free_ char *path = NULL;
|
||||||
const char *authority;
|
const char *authority;
|
||||||
const char *display;
|
const char *display;
|
||||||
|
@ -649,8 +650,18 @@ int _wfd_fn_session_properties_changed(struct wfd_session *s, char **names)
|
||||||
names);
|
names);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int wfd_dbus_shutdown(sd_bus_message *m,
|
||||||
|
void *userdata,
|
||||||
|
sd_bus_error *ret_error)
|
||||||
|
{
|
||||||
|
ctl_wfd_shutdown(ctl_wfd_get());
|
||||||
|
|
||||||
|
return sd_bus_reply_method_return(m, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static const sd_bus_vtable wfd_dbus_vtable[] = {
|
static const sd_bus_vtable wfd_dbus_vtable[] = {
|
||||||
SD_BUS_VTABLE_START(0),
|
SD_BUS_VTABLE_START(0),
|
||||||
|
SD_BUS_METHOD("Shutdown", NULL, NULL, wfd_dbus_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
SD_BUS_VTABLE_END,
|
SD_BUS_VTABLE_END,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -682,7 +693,7 @@ int wfd_dbus_expose(struct wfd_dbus *wfd_dbus)
|
||||||
int r = sd_bus_add_object_vtable(wfd_dbus->bus,
|
int r = sd_bus_add_object_vtable(wfd_dbus->bus,
|
||||||
NULL,
|
NULL,
|
||||||
"/org/freedesktop/miracle/wfd",
|
"/org/freedesktop/miracle/wfd",
|
||||||
"org.freedesktop.miracle.wfd.Display",
|
"org.freedesktop.miracle.wfd",
|
||||||
wfd_dbus_vtable,
|
wfd_dbus_vtable,
|
||||||
wfd_dbus);
|
wfd_dbus);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <gst/gst.h>
|
|
||||||
#include <gst/base/base.h>
|
|
||||||
#include "wfd-session.h"
|
#include "wfd-session.h"
|
||||||
#include "shl_log.h"
|
#include "shl_log.h"
|
||||||
#include "rtsp.h"
|
#include "rtsp.h"
|
||||||
|
@ -61,8 +59,8 @@ struct wfd_out_session
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
char *audio_dev;
|
char *audio_dev;
|
||||||
|
|
||||||
GstElement *pipeline;
|
/*GstElement *pipeline;*/
|
||||||
GstBus *bus;
|
/*GstBus *bus;*/
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct rtsp_dispatch_entry out_session_rtsp_disp_tbl[];
|
static const struct rtsp_dispatch_entry out_session_rtsp_disp_tbl[];
|
||||||
|
@ -80,7 +78,7 @@ int wfd_out_session_new(struct wfd_session **out,
|
||||||
_shl_free_ char *display_schema = NULL;
|
_shl_free_ char *display_schema = NULL;
|
||||||
_shl_free_ char *display_name = NULL;
|
_shl_free_ char *display_name = NULL;
|
||||||
char *display_param;
|
char *display_param;
|
||||||
_wfd_session_free_ struct wfd_session *s;
|
_wfd_session_unref_ struct wfd_session *s;
|
||||||
struct wfd_out_session *os;
|
struct wfd_out_session *os;
|
||||||
enum wfd_display_type display_type;
|
enum wfd_display_type display_type;
|
||||||
enum wfd_resolution_standard std;
|
enum wfd_resolution_standard std;
|
||||||
|
@ -133,8 +131,7 @@ int wfd_out_session_new(struct wfd_session **out,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->dir = WFD_SESSION_DIR_OUT;
|
wfd_session_init(s, WFD_SESSION_DIR_OUT, out_session_rtsp_disp_tbl);
|
||||||
s->rtsp_disp_tbl = out_session_rtsp_disp_tbl;
|
|
||||||
os->fd = -1;
|
os->fd = -1;
|
||||||
os->sink = sink;
|
os->sink = sink;
|
||||||
os->display_type = display_type;
|
os->display_type = display_type;
|
||||||
|
@ -303,10 +300,10 @@ void wfd_out_session_destroy(struct wfd_session *s)
|
||||||
os->fd = -1;
|
os->fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(os->gst_launch_source) {
|
/*if(os->gst_launch_source) {*/
|
||||||
sd_event_source_unref(os->gst_launch_source);
|
/*sd_event_source_unref(os->gst_launch_source);*/
|
||||||
os->gst_launch_source = NULL;
|
/*os->gst_launch_source = NULL;*/
|
||||||
}
|
/*}*/
|
||||||
|
|
||||||
if(os->audio_dev) {
|
if(os->audio_dev) {
|
||||||
free(os->audio_dev);
|
free(os->audio_dev);
|
||||||
|
@ -323,17 +320,17 @@ void wfd_out_session_destroy(struct wfd_session *s)
|
||||||
os->authority = NULL;
|
os->authority = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(os->bus) {
|
/*if(os->bus) {*/
|
||||||
gst_bus_remove_watch(os->bus);
|
/*gst_bus_remove_watch(os->bus);*/
|
||||||
g_object_unref(os->bus);
|
/*g_object_unref(os->bus);*/
|
||||||
os->bus = NULL;
|
/*os->bus = NULL;*/
|
||||||
}
|
/*}*/
|
||||||
|
|
||||||
if(os->pipeline) {
|
/*if(os->pipeline) {*/
|
||||||
gst_element_set_state(os->pipeline, GST_STATE_NULL);
|
/*gst_element_set_state(os->pipeline, GST_STATE_NULL);*/
|
||||||
g_object_unref(os->pipeline);
|
/*g_object_unref(os->pipeline);*/
|
||||||
os->pipeline = NULL;
|
/*os->pipeline = NULL;*/
|
||||||
}
|
/*}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
int wfd_out_session_initiate_request(struct wfd_session *s)
|
int wfd_out_session_initiate_request(struct wfd_session *s)
|
||||||
|
@ -547,43 +544,43 @@ static int wfd_out_session_request_options(struct wfd_session *s,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean wfd_out_session_handle_gst_message(GstBus *bus,
|
//static gboolean wfd_out_session_handle_gst_message(GstBus *bus,
|
||||||
GstMessage *m,
|
// GstMessage *m,
|
||||||
gpointer userdata)
|
// gpointer userdata)
|
||||||
{
|
//{
|
||||||
struct wfd_session *s = userdata;
|
// struct wfd_session *s = userdata;
|
||||||
struct wfd_out_session *os = userdata;
|
// struct wfd_out_session *os = userdata;
|
||||||
GstState old_state, new_state;
|
// GstState old_state, new_state;
|
||||||
|
//
|
||||||
switch(GST_MESSAGE_TYPE(m)) {
|
// switch(GST_MESSAGE_TYPE(m)) {
|
||||||
case GST_MESSAGE_STATE_CHANGED:
|
// case GST_MESSAGE_STATE_CHANGED:
|
||||||
if(os->pipeline != (void *) GST_MESSAGE_SRC(m)) {
|
// if(os->pipeline != (void *) GST_MESSAGE_SRC(m)) {
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
gst_message_parse_state_changed(m, &old_state, &new_state, NULL);
|
// gst_message_parse_state_changed(m, &old_state, &new_state, NULL);
|
||||||
if(GST_STATE_PLAYING == new_state) {
|
// if(GST_STATE_PLAYING == new_state) {
|
||||||
log_info("stream is playing");
|
// log_info("stream is playing");
|
||||||
wfd_session_set_state(s, WFD_SESSION_STATE_PLAYING);
|
// wfd_session_set_state(s, WFD_SESSION_STATE_PLAYING);
|
||||||
}
|
// }
|
||||||
else if(GST_STATE_PLAYING == old_state &&
|
// else if(GST_STATE_PLAYING == old_state &&
|
||||||
GST_STATE_PAUSED == new_state) {
|
// GST_STATE_PAUSED == new_state) {
|
||||||
log_info("stream is paused");
|
// log_info("stream is paused");
|
||||||
wfd_session_set_state(s, WFD_SESSION_STATE_PAUSED);
|
// wfd_session_set_state(s, WFD_SESSION_STATE_PAUSED);
|
||||||
}
|
// }
|
||||||
break;
|
// break;
|
||||||
case GST_MESSAGE_EOS:
|
// case GST_MESSAGE_EOS:
|
||||||
case GST_MESSAGE_ERROR:
|
// case GST_MESSAGE_ERROR:
|
||||||
log_warning("%s encounter unexpected error or EOS",
|
// log_warning("%s encounter unexpected error or EOS",
|
||||||
GST_MESSAGE_SRC_NAME(m));
|
// GST_MESSAGE_SRC_NAME(m));
|
||||||
wfd_session_teardown(s);
|
// wfd_session_teardown(s);
|
||||||
break;
|
// break;
|
||||||
default:
|
// default:
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return TRUE;
|
// return TRUE;
|
||||||
}
|
//}
|
||||||
|
|
||||||
inline static char * uint16_to_str(uint16_t i, char *buf, size_t len)
|
inline static char * uint16_to_str(uint16_t i, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -599,188 +596,188 @@ inline static char * quote_str(const char *s, char *d, size_t len)
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wfd_out_session_create_pipeline(struct wfd_session *s)
|
//static int wfd_out_session_create_pipeline(struct wfd_session *s)
|
||||||
{
|
//{
|
||||||
char rrtp_port[16], rrtcp_port[16], lrtcp_port[16];
|
// char rrtp_port[16], rrtcp_port[16], lrtcp_port[16];
|
||||||
char audio_dev[256];
|
// char audio_dev[256];
|
||||||
char vsrc_param1[16] = "", vsrc_param2[16] = "";
|
// char vsrc_param1[16] = "", vsrc_param2[16] = "";
|
||||||
char vsrc_param3[16] = "", vsrc_param4[16] = "";
|
// char vsrc_param3[16] = "", vsrc_param4[16] = "";
|
||||||
struct wfd_out_session *os = wfd_out_session(s);
|
// struct wfd_out_session *os = wfd_out_session(s);
|
||||||
GstElement *pipeline;
|
// GstElement *pipeline;
|
||||||
GstElement *vsrc;
|
// GstElement *vsrc;
|
||||||
GstBus *bus;
|
// GstBus *bus;
|
||||||
GError *error = NULL;
|
// GError *error = NULL;
|
||||||
const char **tmp;
|
// const char **tmp;
|
||||||
int r;
|
// int r;
|
||||||
const char *pipeline_desc[128] = {
|
// const char *pipeline_desc[128] = {
|
||||||
"ximagesrc",
|
// "ximagesrc",
|
||||||
"name=vsrc",
|
// "name=vsrc",
|
||||||
"use-damage=false",
|
// "use-damage=false",
|
||||||
"show-pointer=false",
|
// "show-pointer=false",
|
||||||
vsrc_param1,
|
// vsrc_param1,
|
||||||
vsrc_param2,
|
// vsrc_param2,
|
||||||
vsrc_param3,
|
// vsrc_param3,
|
||||||
vsrc_param4,
|
// vsrc_param4,
|
||||||
"!", "video/x-raw,",
|
// "!", "video/x-raw,",
|
||||||
"framerate=30/1",
|
// "framerate=30/1",
|
||||||
//"!", "vaapipostproc",
|
// //"!", "vaapipostproc",
|
||||||
// "scale-method=2", /* high quality scaling mode */
|
// // "scale-method=2", /* high quality scaling mode */
|
||||||
// "format=3", /* yv12" */
|
// // "format=3", /* yv12" */
|
||||||
//"!", "vaapih264enc",
|
// //"!", "vaapih264enc",
|
||||||
// "rate-control=1",
|
// // "rate-control=1",
|
||||||
// "num-slices=1", /* in WFD spec, one slice per frame */
|
// // "num-slices=1", /* in WFD spec, one slice per frame */
|
||||||
// "max-bframes=0", /* in H264 CHP, no bframe supporting */
|
// // "max-bframes=0", /* in H264 CHP, no bframe supporting */
|
||||||
// "cabac=true", /* in H264 CHP, CABAC entropy codeing is supported, but need more processing to decode */
|
// // "cabac=true", /* in H264 CHP, CABAC entropy codeing is supported, but need more processing to decode */
|
||||||
// "dct8x8=true", /* in H264 CHP, DTC is supported */
|
// // "dct8x8=true", /* in H264 CHP, DTC is supported */
|
||||||
// "cpb-length=50", /* shortent buffer in order to decrease latency */
|
// // "cpb-length=50", /* shortent buffer in order to decrease latency */
|
||||||
// "keyframe-period=30",
|
// // "keyframe-period=30",
|
||||||
// /* "bitrate=62500", */ /* the max bitrate of H264 level 4.2, crashing my dongle, let codec decide */
|
// // /* "bitrate=62500", */ /* the max bitrate of H264 level 4.2, crashing my dongle, let codec decide */
|
||||||
"!", "videoscale",
|
// "!", "videoscale",
|
||||||
"method=0",
|
// "method=0",
|
||||||
"!", "video/x-raw,",
|
// "!", "video/x-raw,",
|
||||||
"width=1920,",
|
// "width=1920,",
|
||||||
"height=1080",
|
// "height=1080",
|
||||||
"!", "videoconvert",
|
// "!", "videoconvert",
|
||||||
"dither=0",
|
// "dither=0",
|
||||||
"!", "video/x-raw,",
|
// "!", "video/x-raw,",
|
||||||
"format=YV12"
|
// "format=YV12"
|
||||||
"!", "x264enc",
|
// "!", "x264enc",
|
||||||
"pass=4", /* constant quantizer */
|
// "pass=4", /* constant quantizer */
|
||||||
"b-adapt=false", /* no bframe suppport in CHP */
|
// "b-adapt=false", /* no bframe suppport in CHP */
|
||||||
"key-int-max=30", /* send IDR pictures per second */
|
// "key-int-max=30", /* send IDR pictures per second */
|
||||||
"speed-preset=4", /* faster */
|
// "speed-preset=4", /* faster */
|
||||||
"tune=4", /* zero latency */
|
// "tune=4", /* zero latency */
|
||||||
"!", "h264parse",
|
// "!", "h264parse",
|
||||||
"!", "video/x-h264,",
|
// "!", "video/x-h264,",
|
||||||
"alignment=nal,",
|
// "alignment=nal,",
|
||||||
"stream-format=byte-stream"
|
// "stream-format=byte-stream"
|
||||||
"!", "queue",
|
// "!", "queue",
|
||||||
"max-size-buffers=0",
|
// "max-size-buffers=0",
|
||||||
"max-size-bytes=0",
|
// "max-size-bytes=0",
|
||||||
"!", "mpegtsmux",
|
// "!", "mpegtsmux",
|
||||||
"name=muxer",
|
// "name=muxer",
|
||||||
"!", "rtpmp2tpay",
|
// "!", "rtpmp2tpay",
|
||||||
"!", ".send_rtp_sink_0", "rtpbin",
|
// "!", ".send_rtp_sink_0", "rtpbin",
|
||||||
"name=session",
|
// "name=session",
|
||||||
"do-retransmission=true",
|
// "do-retransmission=true",
|
||||||
"do-sync-event=true",
|
// "do-sync-event=true",
|
||||||
"do-lost=true",
|
// "do-lost=true",
|
||||||
"ntp-time-source=3",
|
// "ntp-time-source=3",
|
||||||
"buffer-mode=0",
|
// "buffer-mode=0",
|
||||||
"latency=20",
|
// "latency=20",
|
||||||
"max-misorder-time=30",
|
// "max-misorder-time=30",
|
||||||
"!", "application/x-rtp",
|
// "!", "application/x-rtp",
|
||||||
"!", "udpsink",
|
// "!", "udpsink",
|
||||||
"sync=false",
|
// "sync=false",
|
||||||
"async=false",
|
// "async=false",
|
||||||
"host=", wfd_out_session_get_sink(s)->peer->remote_address,
|
// "host=", wfd_out_session_get_sink(s)->peer->remote_address,
|
||||||
"port=", uint16_to_str(s->stream.rtp_port, rrtp_port,sizeof(rrtp_port)),
|
// "port=", uint16_to_str(s->stream.rtp_port, rrtp_port,sizeof(rrtp_port)),
|
||||||
"udpsrc",
|
// "udpsrc",
|
||||||
"address=", wfd_out_session_get_sink(s)->peer->local_address,
|
// "address=", wfd_out_session_get_sink(s)->peer->local_address,
|
||||||
"port=", uint16_to_str(LOCAL_RTCP_PORT, lrtcp_port,sizeof(lrtcp_port)),
|
// "port=", uint16_to_str(LOCAL_RTCP_PORT, lrtcp_port,sizeof(lrtcp_port)),
|
||||||
"reuse=true",
|
// "reuse=true",
|
||||||
"!", "session.recv_rtcp_sink_0",
|
// "!", "session.recv_rtcp_sink_0",
|
||||||
NULL
|
// NULL
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
if(s->stream.rtcp_port) {
|
// if(s->stream.rtcp_port) {
|
||||||
for(tmp = pipeline_desc; *tmp; ++tmp);
|
// for(tmp = pipeline_desc; *tmp; ++tmp);
|
||||||
*tmp ++ = "session.send_rtcp_src_0";
|
// *tmp ++ = "session.send_rtcp_src_0";
|
||||||
*tmp ++ = "!";
|
// *tmp ++ = "!";
|
||||||
*tmp ++ = "udpsink";
|
// *tmp ++ = "udpsink";
|
||||||
*tmp ++ = "host=";
|
// *tmp ++ = "host=";
|
||||||
*tmp ++ = wfd_out_session_get_sink(s)->peer->remote_address;
|
// *tmp ++ = wfd_out_session_get_sink(s)->peer->remote_address;
|
||||||
*tmp ++ = "port=";
|
// *tmp ++ = "port=";
|
||||||
*tmp ++ = uint16_to_str(s->stream.rtcp_port, rrtcp_port,sizeof(rrtcp_port));
|
// *tmp ++ = uint16_to_str(s->stream.rtcp_port, rrtcp_port,sizeof(rrtcp_port));
|
||||||
*tmp ++ = "sync=false";
|
// *tmp ++ = "sync=false";
|
||||||
*tmp ++ = "async=false";
|
// *tmp ++ = "async=false";
|
||||||
*tmp ++ = NULL;
|
// *tmp ++ = NULL;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if(*os->audio_dev) {
|
// if(*os->audio_dev) {
|
||||||
for(tmp = pipeline_desc; *tmp; ++tmp);
|
// for(tmp = pipeline_desc; *tmp; ++tmp);
|
||||||
*tmp ++ = "pulsesrc";
|
// *tmp ++ = "pulsesrc";
|
||||||
*tmp ++ = "do-timestamp=true";
|
// *tmp ++ = "do-timestamp=true";
|
||||||
*tmp ++ = "client-name=miraclecast";
|
// *tmp ++ = "client-name=miraclecast";
|
||||||
*tmp ++ = "device=";
|
// *tmp ++ = "device=";
|
||||||
*tmp ++ = quote_str(os->audio_dev, audio_dev, sizeof(audio_dev));
|
// *tmp ++ = quote_str(os->audio_dev, audio_dev, sizeof(audio_dev));
|
||||||
*tmp ++ = "!";
|
// *tmp ++ = "!";
|
||||||
*tmp ++ = "voaacenc";
|
// *tmp ++ = "voaacenc";
|
||||||
*tmp ++ = "mark-granule=true";
|
// *tmp ++ = "mark-granule=true";
|
||||||
*tmp ++ = "hard-resync=true";
|
// *tmp ++ = "hard-resync=true";
|
||||||
*tmp ++ = "tolerance=40";
|
// *tmp ++ = "tolerance=40";
|
||||||
*tmp ++ = "!";
|
// *tmp ++ = "!";
|
||||||
*tmp ++ = "audio/mpeg,";
|
// *tmp ++ = "audio/mpeg,";
|
||||||
*tmp ++ = "rate=48000,";
|
// *tmp ++ = "rate=48000,";
|
||||||
*tmp ++ = "channels=2,";
|
// *tmp ++ = "channels=2,";
|
||||||
*tmp ++ = "stream-format=adts,";
|
// *tmp ++ = "stream-format=adts,";
|
||||||
*tmp ++ = "base-profile=lc";
|
// *tmp ++ = "base-profile=lc";
|
||||||
*tmp ++ = "!";
|
// *tmp ++ = "!";
|
||||||
*tmp ++ = "queue";
|
// *tmp ++ = "queue";
|
||||||
*tmp ++ = "max-size-buffers=0";
|
// *tmp ++ = "max-size-buffers=0";
|
||||||
*tmp ++ = "max-size-bytes=0";
|
// *tmp ++ = "max-size-bytes=0";
|
||||||
*tmp ++ = "max-size-time=0";
|
// *tmp ++ = "max-size-time=0";
|
||||||
*tmp ++ = "!";
|
// *tmp ++ = "!";
|
||||||
*tmp ++ = "muxer.";
|
// *tmp ++ = "muxer.";
|
||||||
*tmp ++ = NULL;
|
// *tmp ++ = NULL;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/* bad pratice, but since we are in the same process,
|
// /* bad pratice, but since we are in the same process,
|
||||||
I think this is the only way to do it */
|
// I think this is the only way to do it */
|
||||||
if(WFD_DISPLAY_TYPE_X == os->display_type) {
|
// if(WFD_DISPLAY_TYPE_X == os->display_type) {
|
||||||
r = setenv("XAUTHORITY", os->authority, 1);
|
// r = setenv("XAUTHORITY", os->authority, 1);
|
||||||
if(0 > r) {
|
// if(0 > r) {
|
||||||
return r;
|
// return r;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
r = setenv("DISPLAY", os->display_name, 1);
|
// r = setenv("DISPLAY", os->display_name, 1);
|
||||||
if(0 > r) {
|
// if(0 > r) {
|
||||||
return r;
|
// return r;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if(!os->display_param_name) {
|
// if(!os->display_param_name) {
|
||||||
snprintf(vsrc_param1, sizeof(vsrc_param1), "startx=%hu", os->x);
|
// snprintf(vsrc_param1, sizeof(vsrc_param1), "startx=%hu", os->x);
|
||||||
snprintf(vsrc_param2, sizeof(vsrc_param2), "starty=%hu", os->y);
|
// snprintf(vsrc_param2, sizeof(vsrc_param2), "starty=%hu", os->y);
|
||||||
snprintf(vsrc_param3, sizeof(vsrc_param3), "endx=%d", os->x + os->width - 1);
|
// snprintf(vsrc_param3, sizeof(vsrc_param3), "endx=%d", os->x + os->width - 1);
|
||||||
snprintf(vsrc_param4, sizeof(vsrc_param4), "endy=%d", os->y + os->height - 1);
|
// snprintf(vsrc_param4, sizeof(vsrc_param4), "endy=%d", os->y + os->height - 1);
|
||||||
}
|
// }
|
||||||
else if(!strcmp("xid", os->display_param_name) ||
|
// else if(!strcmp("xid", os->display_param_name) ||
|
||||||
!strcmp("xname", os->display_param_name)) {
|
// !strcmp("xname", os->display_param_name)) {
|
||||||
snprintf(vsrc_param1, sizeof(vsrc_param1),
|
// snprintf(vsrc_param1, sizeof(vsrc_param1),
|
||||||
"%s=\"%s\"",
|
// "%s=\"%s\"",
|
||||||
os->display_param_name,
|
// os->display_param_name,
|
||||||
os->display_param_value);
|
// os->display_param_value);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
pipeline = gst_parse_launchv(pipeline_desc, &error);
|
// pipeline = gst_parse_launchv(pipeline_desc, &error);
|
||||||
if(!pipeline) {
|
// if(!pipeline) {
|
||||||
if(error) {
|
// if(error) {
|
||||||
log_error("failed to create pipeline: %s", error->message);
|
// log_error("failed to create pipeline: %s", error->message);
|
||||||
g_error_free(error);
|
// g_error_free(error);
|
||||||
}
|
// }
|
||||||
return -1;
|
// return -1;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
vsrc = gst_bin_get_by_name(GST_BIN(pipeline), "vsrc");
|
// vsrc = gst_bin_get_by_name(GST_BIN(pipeline), "vsrc");
|
||||||
gst_base_src_set_live(GST_BASE_SRC(vsrc), true);
|
// gst_base_src_set_live(GST_BASE_SRC(vsrc), true);
|
||||||
g_object_unref(vsrc);
|
// g_object_unref(vsrc);
|
||||||
vsrc = NULL;
|
// vsrc = NULL;
|
||||||
|
//
|
||||||
r = gst_element_set_state(pipeline, GST_STATE_PAUSED);
|
// r = gst_element_set_state(pipeline, GST_STATE_PAUSED);
|
||||||
if(GST_STATE_CHANGE_FAILURE == r) {
|
// if(GST_STATE_CHANGE_FAILURE == r) {
|
||||||
g_object_unref(pipeline);
|
// g_object_unref(pipeline);
|
||||||
return -1;
|
// return -1;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
bus = gst_element_get_bus(pipeline);
|
// bus = gst_element_get_bus(pipeline);
|
||||||
gst_bus_add_watch(bus, wfd_out_session_handle_gst_message, s);
|
// gst_bus_add_watch(bus, wfd_out_session_handle_gst_message, s);
|
||||||
|
//
|
||||||
os->pipeline = pipeline;
|
// os->pipeline = pipeline;
|
||||||
os->bus = bus;
|
// os->bus = bus;
|
||||||
|
//
|
||||||
return 0;
|
// return 0;
|
||||||
}
|
//}
|
||||||
|
|
||||||
static int wfd_out_session_handle_pause_request(struct wfd_session *s,
|
static int wfd_out_session_handle_pause_request(struct wfd_session *s,
|
||||||
struct rtsp_message *req,
|
struct rtsp_message *req,
|
||||||
|
@ -789,10 +786,10 @@ static int wfd_out_session_handle_pause_request(struct wfd_session *s,
|
||||||
_rtsp_message_unref_ struct rtsp_message *m = NULL;
|
_rtsp_message_unref_ struct rtsp_message *m = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = gst_element_set_state(wfd_out_session(s)->pipeline, GST_STATE_READY);
|
// r = gst_element_set_state(wfd_out_session(s)->pipeline, GST_STATE_READY);
|
||||||
if(GST_STATE_CHANGE_FAILURE == r) {
|
// if(GST_STATE_CHANGE_FAILURE == r) {
|
||||||
return -1;
|
// return -1;
|
||||||
}
|
// }
|
||||||
|
|
||||||
r = rtsp_message_new_reply_for(req,
|
r = rtsp_message_new_reply_for(req,
|
||||||
&m,
|
&m,
|
||||||
|
@ -815,18 +812,19 @@ static int wfd_out_session_handle_teardown_request(struct wfd_session *s,
|
||||||
_rtsp_message_unref_ struct rtsp_message *m = NULL;
|
_rtsp_message_unref_ struct rtsp_message *m = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
gst_element_set_state(wfd_out_session(s)->pipeline, GST_STATE_NULL);
|
wfd_session_set_state(s, WFD_SESSION_STATE_TEARING_DOWN);
|
||||||
|
/*gst_element_set_state(wfd_out_session(s)->pipeline, GST_STATE_NULL);*/
|
||||||
|
|
||||||
r = rtsp_message_new_reply_for(req,
|
/*r = rtsp_message_new_reply_for(req,*/
|
||||||
&m,
|
/*&m,*/
|
||||||
RTSP_CODE_OK,
|
/*RTSP_CODE_OK,*/
|
||||||
NULL);
|
/*NULL);*/
|
||||||
if(0 > r) {
|
/*if(0 > r) {*/
|
||||||
return r;
|
/*return r;*/
|
||||||
}
|
/*}*/
|
||||||
|
|
||||||
*out_rep = m;
|
/**out_rep = m;*/
|
||||||
m = NULL;
|
/*m = NULL;*/
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -836,17 +834,19 @@ static int wfd_out_session_post_handle_play(sd_event_source *source,
|
||||||
void *userdata)
|
void *userdata)
|
||||||
{
|
{
|
||||||
struct wfd_session *s = userdata;
|
struct wfd_session *s = userdata;
|
||||||
GstStateChangeReturn r;
|
//GstStateChangeReturn r;
|
||||||
|
|
||||||
sd_event_source_unref(source);
|
sd_event_source_unref(source);
|
||||||
wfd_out_session(s)->gst_launch_source = NULL;
|
wfd_out_session(s)->gst_launch_source = NULL;
|
||||||
|
|
||||||
r = gst_element_set_state(wfd_out_session(s)->pipeline,
|
/*r = gst_element_set_state(wfd_out_session(s)->pipeline,*/
|
||||||
GST_STATE_PLAYING);
|
/*GST_STATE_PLAYING);*/
|
||||||
if(GST_STATE_CHANGE_FAILURE == r) {
|
/*if(GST_STATE_CHANGE_FAILURE == r) {*/
|
||||||
wfd_session_teardown(s);
|
/*wfd_session_teardown(s);*/
|
||||||
return -1;
|
/*return -1;*/
|
||||||
}
|
/*}*/
|
||||||
|
|
||||||
|
wfd_session_set_state(s, WFD_SESSION_STATE_PLAYING);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -972,10 +972,10 @@ static int wfd_out_session_handle_setup_request(struct wfd_session *s,
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = wfd_out_session_create_pipeline(s);
|
/*r = wfd_out_session_create_pipeline(s);*/
|
||||||
if(0 > r) {
|
/*if(0 > r) {*/
|
||||||
return r;
|
/*return r;*/
|
||||||
}
|
/*}*/
|
||||||
|
|
||||||
*out_rep = m;
|
*out_rep = m;
|
||||||
m = NULL;
|
m = NULL;
|
||||||
|
|
|
@ -46,6 +46,11 @@ extern int wfd_out_session_teardown(struct wfd_session *);
|
||||||
extern void wfd_out_session_end(struct wfd_session *);
|
extern void wfd_out_session_end(struct wfd_session *);
|
||||||
extern void wfd_out_session_destroy(struct wfd_session *);
|
extern void wfd_out_session_destroy(struct wfd_session *);
|
||||||
static const char * rtsp_message_id_to_string(enum rtsp_message_id id);
|
static const char * rtsp_message_id_to_string(enum rtsp_message_id id);
|
||||||
|
static int wfd_session_handle_request(struct rtsp *bus,
|
||||||
|
struct rtsp_message *m,
|
||||||
|
void *userdata);
|
||||||
|
static bool wfd_session_is_hup(struct wfd_session *s);
|
||||||
|
static void wfd_session_hup(struct wfd_session *s);
|
||||||
|
|
||||||
const struct wfd_session_vtable session_vtbl[] = {
|
const struct wfd_session_vtable session_vtbl[] = {
|
||||||
[WFD_SESSION_DIR_OUT] = {
|
[WFD_SESSION_DIR_OUT] = {
|
||||||
|
@ -177,11 +182,9 @@ int wfd_session_pause(struct wfd_session *s)
|
||||||
|
|
||||||
int wfd_session_teardown(struct wfd_session *s)
|
int wfd_session_teardown(struct wfd_session *s)
|
||||||
{
|
{
|
||||||
|
log_info("wfd_session_teardown(%p)", s);
|
||||||
assert(wfd_is_session(s));
|
assert(wfd_is_session(s));
|
||||||
|
|
||||||
/* notify and detach from sink */
|
|
||||||
wfd_fn_out_session_ended(s);
|
|
||||||
|
|
||||||
if(wfd_session_is_established(s)) {
|
if(wfd_session_is_established(s)) {
|
||||||
if(!session_vtbl[s->dir].teardown) {
|
if(!session_vtbl[s->dir].teardown) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -189,18 +192,36 @@ int wfd_session_teardown(struct wfd_session *s)
|
||||||
|
|
||||||
return session_vtbl[s->dir].teardown(s);;
|
return session_vtbl[s->dir].teardown(s);;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
//wfd_session_free(s);
|
/* notify and detach from sink */
|
||||||
|
wfd_fn_out_session_ended(s);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wfd_session_free(struct wfd_session *s)
|
struct wfd_session * wfd_session_ref(struct wfd_session *s)
|
||||||
|
{
|
||||||
|
if(s) {
|
||||||
|
++ s->ref_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wfd_session_unref(struct wfd_session *s)
|
||||||
{
|
{
|
||||||
if(!s) {
|
if(!s) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(1 <= s->ref_count);
|
||||||
|
|
||||||
|
-- s->ref_count;
|
||||||
|
if(s->ref_count) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(session_vtbl[s->dir].destroy) {
|
if(session_vtbl[s->dir].destroy) {
|
||||||
(*session_vtbl[s->dir].destroy)(s);
|
(*session_vtbl[s->dir].destroy)(s);
|
||||||
}
|
}
|
||||||
|
@ -220,11 +241,7 @@ void wfd_session_free(struct wfd_session *s)
|
||||||
s->stream.url = NULL;
|
s->stream.url = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(s->rtsp) {
|
wfd_session_hup(s);
|
||||||
rtsp_detach_event(s->rtsp);
|
|
||||||
rtsp_unref(s->rtsp);
|
|
||||||
s->rtsp = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
s->rtp_ports[0] = 0;
|
s->rtp_ports[0] = 0;
|
||||||
s->rtp_ports[1] = 0;
|
s->rtp_ports[1] = 0;
|
||||||
|
@ -400,7 +417,7 @@ static int wfd_session_handle_request(struct rtsp *bus,
|
||||||
_rtsp_message_unref_ struct rtsp_message *rep = NULL;
|
_rtsp_message_unref_ struct rtsp_message *rep = NULL;
|
||||||
struct wfd_session *s = userdata;
|
struct wfd_session *s = userdata;
|
||||||
enum rtsp_message_id id;
|
enum rtsp_message_id id;
|
||||||
char date[128];
|
char date[64];
|
||||||
uint64_t usec;
|
uint64_t usec;
|
||||||
time_t sec;
|
time_t sec;
|
||||||
int r;
|
int r;
|
||||||
|
@ -427,6 +444,11 @@ static int wfd_session_handle_request(struct rtsp *bus,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(WFD_SESSION_STATE_TEARING_DOWN == wfd_session_get_state(s)) {
|
||||||
|
wfd_session_hup(s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
r = sd_event_now(ctl_wfd_get_loop(), CLOCK_REALTIME, &usec);
|
r = sd_event_now(ctl_wfd_get_loop(), CLOCK_REALTIME, &usec);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -437,7 +459,7 @@ static int wfd_session_handle_request(struct rtsp *bus,
|
||||||
"%a, %d %b %Y %T %z",
|
"%a, %d %b %Y %T %z",
|
||||||
gmtime(&sec));
|
gmtime(&sec));
|
||||||
|
|
||||||
r = rtsp_message_append(rep, "<s>", "Date", date);
|
r = rtsp_message_append(rep, "<&>", "Date", date);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -515,6 +537,17 @@ error:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int wfd_session_init(struct wfd_session *s,
|
||||||
|
enum wfd_session_dir dir,
|
||||||
|
const struct rtsp_dispatch_entry *disp_tbl)
|
||||||
|
{
|
||||||
|
s->ref_count = 1;
|
||||||
|
s->dir = dir;
|
||||||
|
s->rtsp_disp_tbl = disp_tbl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int wfd_session_request(struct wfd_session *s,
|
int wfd_session_request(struct wfd_session *s,
|
||||||
enum rtsp_message_id id,
|
enum rtsp_message_id id,
|
||||||
const struct wfd_arg_list *args)
|
const struct wfd_arg_list *args)
|
||||||
|
@ -589,6 +622,8 @@ static int wfd_session_handle_io(sd_event_source *source,
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_trace("rtsp->ref = %ld", *(unsigned long *) rtsp);
|
||||||
|
|
||||||
conn = -1;
|
conn = -1;
|
||||||
|
|
||||||
r = rtsp_attach_event(rtsp, ctl_wfd_get_loop(), 0);
|
r = rtsp_attach_event(rtsp, ctl_wfd_get_loop(), 0);
|
||||||
|
@ -622,6 +657,23 @@ end:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool wfd_session_is_hup(struct wfd_session *s)
|
||||||
|
{
|
||||||
|
return NULL == s->rtsp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wfd_session_hup(struct wfd_session *s)
|
||||||
|
{
|
||||||
|
if(!s || !s->rtsp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtsp_remove_match(s->rtsp, wfd_session_handle_request, s);
|
||||||
|
rtsp_detach_event(s->rtsp);
|
||||||
|
rtsp_unref(s->rtsp);
|
||||||
|
s->rtsp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int wfd_session_start(struct wfd_session *s, uint64_t id)
|
int wfd_session_start(struct wfd_session *s, uint64_t id)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
@ -658,9 +710,11 @@ int wfd_session_start(struct wfd_session *s, uint64_t id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wfd_session_free_p(struct wfd_session **s)
|
void wfd_session_unrefp(struct wfd_session **s)
|
||||||
{
|
{
|
||||||
wfd_session_free(*s);
|
if(s) {
|
||||||
|
wfd_session_unref(*s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * rtsp_message_id_to_string(enum rtsp_message_id id)
|
static const char * rtsp_message_id_to_string(enum rtsp_message_id id)
|
||||||
|
|
|
@ -93,6 +93,7 @@ struct wfd_session_vtable
|
||||||
|
|
||||||
struct wfd_session
|
struct wfd_session
|
||||||
{
|
{
|
||||||
|
int ref_count;
|
||||||
enum wfd_session_dir dir;
|
enum wfd_session_dir dir;
|
||||||
enum wfd_session_state state;
|
enum wfd_session_state state;
|
||||||
enum rtsp_message_id last_request;
|
enum rtsp_message_id last_request;
|
||||||
|
@ -112,7 +113,9 @@ struct wfd_session
|
||||||
} stream;
|
} stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
int wfd_session_init(struct wfd_session *s);
|
int wfd_session_init(struct wfd_session *s,
|
||||||
|
enum wfd_session_dir dir,
|
||||||
|
const struct rtsp_dispatch_entry *disp_tbl);
|
||||||
int wfd_session_gen_stream_url(struct wfd_session *s,
|
int wfd_session_gen_stream_url(struct wfd_session *s,
|
||||||
const char *local_addr,
|
const char *local_addr,
|
||||||
enum wfd_stream_id id);
|
enum wfd_stream_id id);
|
||||||
|
|
|
@ -45,9 +45,10 @@ static int wfd_sink_set_session(struct wfd_sink *sink,
|
||||||
ctl_wfd_remove_session_by_id(ctl_wfd_get(),
|
ctl_wfd_remove_session_by_id(ctl_wfd_get(),
|
||||||
wfd_session_get_id(sink->session),
|
wfd_session_get_id(sink->session),
|
||||||
NULL);
|
NULL);
|
||||||
|
wfd_session_unref(sink->session);
|
||||||
}
|
}
|
||||||
|
|
||||||
sink->session = session;
|
sink->session = session ? wfd_session_ref(session) : NULL;
|
||||||
wfd_fn_sink_properties_changed(sink, "Session");
|
wfd_fn_sink_properties_changed(sink, "Session");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -90,11 +91,7 @@ void wfd_sink_free(struct wfd_sink *sink)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sink->session) {
|
wfd_sink_set_session(sink, NULL);
|
||||||
s = sink->session;
|
|
||||||
wfd_sink_set_session(sink, NULL);
|
|
||||||
wfd_session_free(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(sink->label) {
|
if(sink->label) {
|
||||||
free(sink->label);
|
free(sink->label);
|
||||||
|
@ -129,7 +126,7 @@ int wfd_sink_start_session(struct wfd_sink *sink,
|
||||||
const char *audio_dev)
|
const char *audio_dev)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
_wfd_session_free_ struct wfd_session *s = NULL;
|
_wfd_session_unref_ struct wfd_session *s = NULL;
|
||||||
|
|
||||||
assert(sink);
|
assert(sink);
|
||||||
assert(out);
|
assert(out);
|
||||||
|
@ -165,7 +162,6 @@ int wfd_sink_start_session(struct wfd_sink *sink,
|
||||||
|
|
||||||
sink->session = s;
|
sink->session = s;
|
||||||
*out = s;
|
*out = s;
|
||||||
s = NULL;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue