mirror of
https://github.com/albfan/miraclecast.git
synced 2025-02-13 10:11:54 +00:00
miracle-wfdctl: user now can select video mode through DBus interface
This commit is contained in:
parent
85c8988b38
commit
c6ef0d3f69
7 changed files with 177 additions and 20 deletions
|
@ -199,6 +199,6 @@ invoke org.freedesktop.miracle.wfd \
|
|||
/org/freedesktop/miracle/wfd/sink/$peer_id \
|
||||
org.freedesktop.miracle.wfd.Sink \
|
||||
Peer /org/freedesktop/miracle/wifi/peer/$peer_id \
|
||||
StartSession
|
||||
StartSession sqqqq 'x://:0.0' 0 0 1920 1080
|
||||
|
||||
wait
|
||||
|
|
|
@ -170,7 +170,13 @@ enum wfd_session_state
|
|||
WFD_SESSION_STATE_TEARING_DOWN,
|
||||
};
|
||||
|
||||
int wfd_out_session_new(struct wfd_session **out, struct wfd_sink *sink);
|
||||
int wfd_out_session_new(struct wfd_session **out,
|
||||
struct wfd_sink *sink,
|
||||
const char *display,
|
||||
uint16_t x,
|
||||
uint16_t y,
|
||||
uint16_t width,
|
||||
uint16_t height);
|
||||
int wfd_session_start(struct wfd_session *s, uint64_t id);
|
||||
enum wfd_session_dir wfd_session_get_dir(struct wfd_session *s);
|
||||
uint64_t wfd_session_get_id(struct wfd_session *s);
|
||||
|
@ -211,7 +217,12 @@ void wfd_sink_free(struct wfd_sink *sink);
|
|||
const char * wfd_sink_get_label(struct wfd_sink *sink);
|
||||
const union wfd_sube * wfd_sink_get_dev_info(struct wfd_sink *sink);
|
||||
int wfd_sink_start_session(struct wfd_sink *sink,
|
||||
struct wfd_session **session);
|
||||
struct wfd_session **out,
|
||||
const char *display,
|
||||
uint16_t x,
|
||||
uint16_t y,
|
||||
uint16_t width,
|
||||
uint16_t height);
|
||||
void wfd_sink_handle_session_ended(struct wfd_sink *sink);
|
||||
bool wfd_sink_is_session_started(struct wfd_sink *sink);
|
||||
static inline void wfd_sink_freep(struct wfd_sink **s)
|
||||
|
|
|
@ -376,7 +376,19 @@ static int wfd_dbus_sink_start_session(sd_bus_message *m,
|
|||
struct wfd_sink *sink = userdata;
|
||||
_wfd_session_free_ struct wfd_session *session = NULL;
|
||||
_shl_free_ char *path = NULL;
|
||||
int r = wfd_sink_start_session(sink, &session);
|
||||
char *display = NULL;
|
||||
uint16_t x, y, width, height;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_read(m, "sqqqq", &display, &x, &y, &width, &height);
|
||||
if(0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = wfd_sink_start_session(sink,
|
||||
&session,
|
||||
display,
|
||||
x, y, width, height);
|
||||
if(0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
@ -610,7 +622,7 @@ static const sd_bus_vtable wfd_dbus_vtable[] = {
|
|||
|
||||
static const sd_bus_vtable wfd_dbus_sink_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_METHOD("StartSession", NULL, "o", wfd_dbus_sink_start_session, 0),
|
||||
SD_BUS_METHOD("StartSession", "sqqqq", "o", wfd_dbus_sink_start_session, 0),
|
||||
/*SD_BUS_PROPERTY("AudioFormats", "a{sv}", wfd_dbus_sink_get_audio_formats, 0, SD_BUS_VTABLE_PROPERTY_CONST),*/
|
||||
/*SD_BUS_PROPERTY("VideoFormats", "a{sv}", wfd_dbus_sink_get_video_formats, 0, SD_BUS_VTABLE_PROPERTY_CONST),*/
|
||||
/*SD_BUS_PROPERTY("HasAudio", "b", wfd_dbus_sink_has_audio, 0, SD_BUS_VTABLE_PROPERTY_CONST),*/
|
||||
|
|
|
@ -21,11 +21,18 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include "wfd-session.h"
|
||||
#include "shl_log.h"
|
||||
#include "rtsp.h"
|
||||
|
||||
enum wfd_display_type
|
||||
{
|
||||
WFD_DISPLAY_TYPE_UNKNOWN,
|
||||
WFD_DISPLAY_TYPE_X,
|
||||
};
|
||||
|
||||
struct wfd_out_session
|
||||
{
|
||||
struct wfd_session parent;
|
||||
|
@ -33,15 +40,59 @@ struct wfd_out_session
|
|||
int fd;
|
||||
sd_event_source *gst_launch_source;
|
||||
sd_event_source *gst_term_source;
|
||||
|
||||
enum wfd_display_type display_type;
|
||||
char *display_name;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
enum wfd_resolution_standard std;
|
||||
uint32_t mask;
|
||||
};
|
||||
|
||||
static const struct rtsp_dispatch_entry out_session_rtsp_disp_tbl[];
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
int wfd_out_session_new(struct wfd_session **out, struct wfd_sink *sink)
|
||||
int wfd_out_session_new(struct wfd_session **out,
|
||||
struct wfd_sink *sink,
|
||||
const char *display,
|
||||
uint16_t x,
|
||||
uint16_t y,
|
||||
uint16_t width,
|
||||
uint16_t height)
|
||||
{
|
||||
struct wfd_out_session *s = calloc(1, sizeof(struct wfd_out_session));
|
||||
_shl_free_ char *display_schema = NULL;
|
||||
_shl_free_ char *display_name = NULL;
|
||||
enum wfd_display_type display_type;
|
||||
struct wfd_out_session *s;
|
||||
enum wfd_resolution_standard std;
|
||||
uint32_t mask;
|
||||
int r;
|
||||
|
||||
r = sscanf(display, "%m[^:]://%ms",
|
||||
&display_schema,
|
||||
&display_name);
|
||||
if(r != 2) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if(!strcmp("x", display_schema)) {
|
||||
display_type = WFD_DISPLAY_TYPE_X;
|
||||
}
|
||||
else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if(!width || !height) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = vfd_get_mask_from_resolution(width, height, &std, &mask);
|
||||
if(0 > r) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s = calloc(1, sizeof(struct wfd_out_session));
|
||||
if(!s) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -50,6 +101,15 @@ int wfd_out_session_new(struct wfd_session **out, struct wfd_sink *sink)
|
|||
wfd_session(s)->rtsp_disp_tbl = out_session_rtsp_disp_tbl;
|
||||
s->fd = -1;
|
||||
s->sink = sink;
|
||||
s->display_type = display_type;
|
||||
s->display_name = display_name;
|
||||
display_name = NULL;
|
||||
s->x = x;
|
||||
s->y = y;
|
||||
s->width = width;
|
||||
s->height = height;
|
||||
s->mask = mask;
|
||||
s->std = std;
|
||||
|
||||
*out = wfd_session(s);
|
||||
|
||||
|
@ -215,6 +275,11 @@ void wfd_out_session_destroy(struct wfd_session *s)
|
|||
os->gst_launch_source = NULL;
|
||||
}
|
||||
|
||||
if(os->display_name) {
|
||||
free(os->display_name);
|
||||
os->display_name = NULL;
|
||||
}
|
||||
|
||||
wfd_out_session_kill_gst(s);
|
||||
}
|
||||
|
||||
|
@ -429,19 +494,27 @@ static int wfd_out_session_request_options(struct wfd_session *s,
|
|||
return 0;
|
||||
}
|
||||
|
||||
inline static char * uint16_to_str(uint16_t i, char *buf, size_t len)
|
||||
{
|
||||
snprintf(buf, len, "%u", i);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int wfd_out_session_launch_gst(struct wfd_session *s, pid_t *out)
|
||||
{
|
||||
sigset_t sigset;
|
||||
char port[10];
|
||||
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",
|
||||
"ximagesrc",
|
||||
"use-damage=false",
|
||||
"show-pointer=false",
|
||||
"startx=0",
|
||||
"starty=0",
|
||||
"endx=1279",
|
||||
"endy=719",
|
||||
"startx=", uint16_to_str(os->x, x, sizeof(x)),
|
||||
"starty=", uint16_to_str(os->x, y, sizeof(y)),
|
||||
"endx=", uint16_to_str(os->width - 1, width, sizeof(width)),
|
||||
"endy=", uint16_to_str(os->height - 1, height, sizeof(height)),
|
||||
"!", "vaapipostproc",
|
||||
"!", "video/x-raw,",
|
||||
"format=YV12",
|
||||
|
@ -454,12 +527,10 @@ static int wfd_out_session_launch_gst(struct wfd_session *s, pid_t *out)
|
|||
"!", "rtpmp2tpay",
|
||||
"!", "udpsink",
|
||||
"host=", wfd_out_session_get_sink(s)->peer->remote_address,
|
||||
"port=", port,
|
||||
"port=", uint16_to_str(s->stream.rtp_port, port, sizeof(port)),
|
||||
NULL
|
||||
};
|
||||
|
||||
snprintf(port, sizeof(port), "%hu", s->stream.rtp_port);
|
||||
|
||||
pid_t p = fork();
|
||||
if(0 > p) {
|
||||
return p;
|
||||
|
@ -748,6 +819,7 @@ static int wfd_out_session_request_set_parameter(struct wfd_session *s,
|
|||
const struct wfd_arg_list *args,
|
||||
struct rtsp_message **out)
|
||||
{
|
||||
struct wfd_out_session *os = wfd_out_session(s);
|
||||
_rtsp_message_unref_ struct rtsp_message *m = NULL;
|
||||
_shl_free_ char *body = NULL;
|
||||
int r;
|
||||
|
@ -762,12 +834,15 @@ 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: 00 00 02 10 00001401 00000000 00000000 00 0000 0000 00 none none\n"
|
||||
"wfd_video_formats: 00 00 02 10 %08X %08X %08X 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"
|
||||
//"wfd_uibc_setting: disable\n",
|
||||
WFD_RESOLUTION_STANDARD_CEA == os->std ? os->mask : 0,
|
||||
WFD_RESOLUTION_STANDARD_VESA == os->std ? os->mask: 0,
|
||||
WFD_RESOLUTION_STANDARD_HH == os->std ? os->mask : 0,
|
||||
wfd_session_get_stream_url(s),
|
||||
s->rtp_ports[0],
|
||||
s->rtp_ports[1]);
|
||||
|
|
|
@ -117,7 +117,13 @@ struct ctl_peer * wfd_sink_get_peer(struct wfd_sink *sink)
|
|||
return sink->peer;
|
||||
}
|
||||
|
||||
int wfd_sink_start_session(struct wfd_sink *sink, struct wfd_session **out)
|
||||
int wfd_sink_start_session(struct wfd_sink *sink,
|
||||
struct wfd_session **out,
|
||||
const char *display,
|
||||
uint16_t x,
|
||||
uint16_t y,
|
||||
uint16_t width,
|
||||
uint16_t height)
|
||||
{
|
||||
int r;
|
||||
_wfd_session_free_ struct wfd_session *s = NULL;
|
||||
|
@ -129,7 +135,7 @@ int wfd_sink_start_session(struct wfd_sink *sink, struct wfd_session **out)
|
|||
return -EALREADY;
|
||||
}
|
||||
|
||||
r = wfd_out_session_new(&s, sink);
|
||||
r = wfd_out_session_new(&s, sink, display, x, y, width, height);
|
||||
if(0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -262,6 +262,55 @@ int vfd_get_hh_resolution(uint32_t mask, int *hres, int *vres)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
int vfd_get_mask_from_resolution(int hres,
|
||||
int vres,
|
||||
enum wfd_resolution_standard *out_std,
|
||||
uint32_t *out_mask)
|
||||
{
|
||||
struct {
|
||||
const struct wfd_resolution *entries;
|
||||
size_t n_entries;
|
||||
} tbls[] = {
|
||||
[WFD_RESOLUTION_STANDARD_CEA] = {
|
||||
resolutions_cea,
|
||||
SHL_ARRAY_LENGTH(resolutions_cea)
|
||||
},
|
||||
[WFD_RESOLUTION_STANDARD_VESA] = {
|
||||
resolutions_vesa,
|
||||
SHL_ARRAY_LENGTH(resolutions_vesa)
|
||||
},
|
||||
[WFD_RESOLUTION_STANDARD_HH] = {
|
||||
resolutions_hh,
|
||||
SHL_ARRAY_LENGTH(resolutions_hh)
|
||||
},
|
||||
};
|
||||
enum wfd_resolution_standard std = WFD_RESOLUTION_STANDARD_CEA;
|
||||
uint32_t mask = 0;
|
||||
size_t n;
|
||||
|
||||
for(; std <= WFD_RESOLUTION_STANDARD_HH; ++ std) {
|
||||
for(n = 0; n < tbls[std].n_entries; ++ n) {
|
||||
if(hres == tbls[std].entries[n].hres &&
|
||||
vres == tbls[std].entries[n].vres) {
|
||||
mask |= 1 << n;
|
||||
}
|
||||
}
|
||||
|
||||
if(mask) {
|
||||
if(out_mask) {
|
||||
*out_mask = mask;
|
||||
}
|
||||
if(out_std) {
|
||||
*out_std = std;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int wfd_sube_parse_device_info(const char *in, union wfd_sube *out)
|
||||
{
|
||||
int r = sscanf(in, "%4hx%4hx%4hx",
|
||||
|
|
|
@ -152,6 +152,10 @@ int wfd_get_resolutions(enum wfd_resolution_standard std,
|
|||
int vfd_get_cea_resolution(uint32_t mask, int *hres, int *vres);
|
||||
int vfd_get_vesa_resolution(uint32_t mask, int *hres, int *vres);
|
||||
int vfd_get_hh_resolution(uint32_t mask, int *hres, int *vres);
|
||||
int vfd_get_mask_from_resolution(int hres,
|
||||
int vres,
|
||||
enum wfd_resolution_standard *out_std,
|
||||
uint32_t *out_mask);
|
||||
int wfd_sube_parse(const char *in, union wfd_sube *out);
|
||||
int wfd_sube_parse_with_id(enum wfd_sube_id id,
|
||||
const char *in,
|
||||
|
|
Loading…
Reference in a new issue